0

On our team's git a given merge commit was performed that deleted a file and we can only see that in tortoisegit log:

TortoiseGit Merge Log

The log for git command-line does not yield the deletion (output of git log --stat ): git log stat command

git log stat output

Trying to figure out what was the actual commit that caused the deletion rendered no results on git gui:

Git Gui log for the second parent

This log shows no file deletion.

So the question is this: How can we, using the git command-line and TortoiseGit, trace this "deletion" fully and prove what commit (merge or not) deleted the file?

Many thanks.

Edit: using torek's feedback, using git log -c --stat and git log --cc --stat still does not show which commit did "delete" the file but it does show more info on merge commits: enter image description here

I've searched the log for the affected file and get only additions and changes on other commits but with git log -m --numstat I do get this:

git log numstat

So apparently lines with that file were present in parent commit 07a2fb4 but not in parent commit d0941f2.

How can I tell what commit "wins" for a particular file in a merge commit so as to detect these missing files?

trankas
  • 11
  • 1
  • 3
  • You don't show what command-line `git log` command you ran (the precise options, including any path name limiters, matter quite a lot) but by default `git log` does not show *any* information about merge commits. Add `-c` or `--cc` (note two dashes for `cc` vs one for `c`) to get *combined diffs*, or `-m` to get *per-parent* diffs (which it seems TortoiseGit is doing). If using path selectors note that this turns on History Simplification. – torek Apr 11 '17 at 09:53
  • Hi, thanks for the feedback. With -c and --cc I do get more info but only additions and modifications to the file that should've been in the git repo and in fact it is not, which caused much confusion. I'll update the question with your feedback as well. – trankas Apr 11 '17 at 10:12
  • The combined diffs deliberately suppress information that, in a "normal" merge, is generally redundant. If the merge was done *wrong* though, this may hide some details. Using `-m` to split the merge into per-parent operations compares the merge result individually against each parent commit; that information is as complete as you get in any diff, but is unwieldy and difficult to interpret. See also http://stackoverflow.com/q/43138569/1256452 – torek Apr 11 '17 at 10:21
  • Thanks I'll definitely look into that. So detection is going to be a manual procedure, right? You have to know which files have to be there to figure out if the merge was done poorly. – trankas Apr 11 '17 at 10:33
  • Pretty much, yes. There is a faster way though, *if* you have some sort of automated test that can identify a "good tree" vs a "bad tree": use `git bisect`. It's some work to set it all up—particularly, writing the test ("file absent" is probably not sufficient as there are probably some commits that *shouldn't* have it)—but after that, if your test is reliable, Git will automatically find the commit where things went wrong. – torek Apr 11 '17 at 10:37
  • BTW, re that last question ("How can I tell what commit "wins" for a particular file in a merge commit"): in a normal merge, neither *file* "wins" (as in, the committed merge result is not just one of the two parent files). Instead, Git compares *each* parent to the *merge-base* version of that file, and combines the two sets of changes. However, if the change from base to parent1 is "modify file" and the change from base to parent2 is "delete file", Git simply declares a merge conflict and forces the person doing the merge to resolve the conflict. [cont'd] – torek Apr 11 '17 at 10:48
  • The same holds if the file is modified from base to parent2 and removed from base to parent1. You get rename/delete conflicts if Git decides that one branch renamed the file and the other deleted it, and the more typical modify/modify conflicts if both parent branches have a change vs the base file *and* those two changes "touch" the same lines. You can always *repeat* a merge by checking out (as a detached head) any given commit by hash ID and then `git merge`ing the other commit by hash ID; this will show you what Git thinks the merge result is, including any conflicts Git declares. – torek Apr 11 '17 at 10:51
  • Thanks for the update. I've been wondering about `git bisect` but our code is for an external tool and writing tests for those is kind of tricky but I'll definitely try to incorporate bisect tests if I can. – trankas Apr 11 '17 at 11:18

1 Answers1

1

The TortoiseGit log dialog shows diffs to both parents on a merge (and might therefore include changes which happend somewhere in between the parent and the merge commit). So:

  1. The file was deleted in the history of the first parent.
  2. The file was deleted in the history of the second parent.
  3. The file was deleted during the merge.

In your reported chase I suppose only case 1 is possible.

In order to see in which commit it was deleted select the file and choose "Show log" and you'll get another log dialog where you can see the history for this specific file (make sure "Show whole project" is not selected in the lower left). The last commit should indicate where this file got deleted. - In order to distinguish the last case you can also select each last commit of the parents and open the repository browser to see whether the file is still there.

To answer you last question: There is no "wins". Git does not care whether a file is present on not in a branch you merge, I just re-applies the changes the changes since the fork (or the last merge) of the to-be-merged branch (if a file was deleted on the current branch and modified on the branch to-be-merged you'll get a conflict, if it was not touched, Git doesn't care for this file).

MrTux
  • 32,350
  • 30
  • 109
  • 146
  • Thanks for the info. Funny enough, I had tried to get the file log from the merge commit that "deleted" it and I get an empty log... – trankas Apr 11 '17 at 13:08
  • How did you try to get the log? Here the way might be important. – MrTux Apr 11 '17 at 14:24
  • I did as you said, I right-clicked the file and made sure that the "Show whole project" was not selected. It only showed commits when ticking the "All branches" option. – trankas Apr 11 '17 at 15:15
  • That's curious. Tried entering the file in the filter of the log dialog? – MrTux Apr 11 '17 at 16:42