1

Something happened to our dev branch such that a lot of code from the release branch got merged into it. I'm trying to track down where these changes occurred but I get some very puzzling results. When I run git diff HEAD@{2} it shows a list of changes including many files that haven't been touched in months, implying that HEAD@{2} is the commit that brought in the bad code as I see it. However if I run git show HEAD@{2} it shows a rather innocuous commit that only touches two files. Further, when I run git reset --hard HEAD@{2} it seems to fix the issues and to top off all the weirdness after I tried that reset twice and then undid it with git reset --hard origin/dev it now appears that the commit with all the extra code is at HEAD@{1}.

I can't seem to make head or tails of this so any suggestions/pointers/tips or tricks would be welcome but some directed questions that are puzzling me are: how can this code have gotten into the branch if there wasn't a merge commit? If someone cherry-picked a commit from a production branch to the dev branch could that be related to this? What are the differences (if any) in how git show and git diff resolve commits?

The current theory I have given limited git knowledge: it seems that these changes weren't part of any commit but somehow got into the tree right around HEAD@{2} so diff shows the changes as it walks the object tree but show doesnt see them as they're not part of a commit. Does this make any sense or am I way off base?

Either way, thanks for any help you can give!

Michoel
  • 834
  • 5
  • 16
  • Every time you move the place to which `HEAD` points, including using `git reset`, the relative numbers change. If you were looking at something and then did `git reset --hard HEAD@{2}` you created a new log entry for HEAD so now you have to use `HEAD@{3}` to refer to the same underlying commit-ID. Just as a point of note, then, I find using raw IDs, or setting a temporary tag, tends to work better for this stuff... – torek Sep 12 '14 at 19:29
  • Interesting, more investigation makes me realize that I now see that changeset in `HEAD@{1}..HEAD@{2}` and `HEAD@{3}..HEAD@{4}` so I guess resetting to `origin/dev` pushed the original one back and added a new one at the top? – Michoel Sep 12 '14 at 19:34
  • Essentially, yes: every time you update a reference name (branch name or `HEAD`, mostly, but "remote branches" have logs as well), git logs the previous name/SHA-1 pair in the "reflog" for that reference (stored in in `.git/logs/`). The `@{...}` syntax tells git to look in the reflog, and a numeric value is "how many to step back from the latest". You can also use `@{yesterday}`, `@{1 hour ago}`, and various other forms, although many require quoting to prevent the shell from mangling them. Use `git reflog` or `git reflog branchname` to view the ref-log for `HEAD` or a specific branch. – torek Sep 12 '14 at 19:58

0 Answers0