44

My colleague did a change a while back - introduced a new function - and that was (successfully) committed to Git. Now, though, that function has gone missing.

Using git log --reverse I've managed to find the last commit where that function was still in the code (48d60a03). The next (e6f28bfd) commit (where the function in question disappeared) is a merge (of 14158e1), but git show'ing any of these does not reveal a delete of the missing code.

In other words, code has disappeared during a merge, without being deleted in either of the branches being merged.

Searching Stack Overflow for a couple of hours leads me to conclude that it must be a manual error during a conflict resolution (did I get that right?). So be it, that happens. The question is - how do I get that code back? Is there another way than making a new commit with the missing code?

Related question; can I somehow find out, if there are other instances of stuff going bye-bye like this? I'm slightly worried ;)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vonsild
  • 587
  • 1
  • 4
  • 7
  • Note that `git show` on a merge commit will only show changes which are not reflected in either branch, e.g. when you manually add additional changes in the merge commit or resolve conflicts. If said code really disappeared in the merge commit then it happened in the other branch. – poke Jul 08 '13 at 13:05
  • 1
    @poke: Another option is that there was a merge conflict involving that function and someone just decided that their code was the best, thereby deleting the function that is now missing. – Arjan Jul 08 '13 at 13:11
  • @Arjan Changes happened in a merge conflict should show up in the diff from `git show`. – poke Jul 08 '13 at 13:14
  • [git bisect](https://git-scm.com/docs/git-bisect) is a nicer way to find the offending the commit instead of having to trawl through history yourself. – Dylan Cali Dec 05 '15 at 21:58
  • I just found your question after I posted a very similar question. http://stackoverflow.com/questions/41862086/changes-lost-after-merge-commit-git-or-atlassian-sourcetree Did you ever find out the source of the "evil merges"? (e.g. although you have an approved answer, noone was really able to answer the real question of how to avoid them in the first place). "test suite"... not exactly getting at the source of the issue. – Charlie Dalsass Jan 26 '17 at 14:58
  • No, I never found the source of this :( It's happened a couple of times since, but luckily on other projects, where we DID have access to testing. – Vonsild Jan 30 '17 at 08:28
  • @Vonsild, was your colleague using TortoiseGit? I've discovered elsewhere that apparently during a merge, TortoiseGit shows a dialog with all the merged files, and a checkbox next to each one. Apparently it's rather inviting to uncheck the files one didn't change oneself...and the result is that those files go missing from the merge, with no record of their deletion. This very thing happened to a colleague of mine. – Ryan Lundy Mar 20 '17 at 09:26
  • 1
    @Kyralessa We use SourceTree and this appears to be what is happening to us. While merging with --no-commit to review the merge people are seeing files they didnt change and unstaging them. Any idea if there is a way to detect when this happens? – Marie Jun 14 '17 at 19:56
  • @Kyralessa That's interesting. It's been a few years, but yes, I actually think he used TortoiseGit at the time. – Vonsild Jun 16 '17 at 08:48
  • got bitten by this bug recently. luckily the changes that did not make to release were not critical or frequently used. – TheVillageIdiot Nov 01 '17 at 01:31
  • This question was shown in [this video](https://www.youtube.com/watch?v=k9WqpQp8VSU&t=12m32s) at 12 min 32 secs. – Peter Mortensen Jun 26 '22 at 10:37

6 Answers6

11

Changes which were committed at some point are hard to lose completely. Try running 'git reflog' and see if you can spot the commit you've lost. Then you can merge it into the current branch by running "git merge [SHA-1 hash value of your lost commit]".

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
alexakarpov
  • 1,848
  • 2
  • 21
  • 39
  • 6
    Trouble is, it is not a missing commit. It's a case of an evil merge. How it happened, I still don't understand, but happen it did. – Vonsild Jul 09 '13 at 07:30
  • You, my friend, have saved my ass and given me back faith in the greater scheme of things. – cmc Jun 06 '14 at 14:15
  • 1
    git-reflog is the local activity log of a repo user, when trying to find something that is cross users, reflog is probably less relevant. – JAR.JAR.beans Jul 22 '14 at 11:12
11

If you know an identifiable section of the code which has been lost, you may be able to find the exact merge which lost your code by using git log -G regexToSearchFor -m --patch

  • -G <regex> tells Git to "Look for differences whose patch text contains added/removed lines that match <regex>"
  • -m tells Git to include merge commits
  • --patch tells Git to show a diff of whatever it finds
alxndr
  • 3,851
  • 3
  • 34
  • 35
  • Thanks, this helped a lot with finding the appropriate commits. A *lot* easier than bisect. However, it showed two where the code was added, none where it was deleted. Still at a loss. – Gringo Suave Jan 10 '19 at 01:27
10

Because your history has already been pushed, the best way is to make a new commit. Otherwise, you run the risk of losing other code and messing up everyone's repos.

Since you know where the commit that last had the function, you can git checkout 48d60a03 -- <name of file with function>. Then you can commit the old/new file with the function.

As there are likely to be other changes in the file, you will probably want to git reset to unstage the file and use git add -p to only add the changes for the function that you are looking for.

For preventing this from happening, my recommendation is to get a comprehensive test suite that you can run after completing a merge. That can help minimize the chances that code will be lost as tests will fail.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Schleis
  • 41,516
  • 7
  • 68
  • 87
  • 5
    I'd give my right arm for a comprehensive test suite, but sadly, that does not seem to be an option. – Vonsild Jul 09 '13 at 07:28
  • 8
    Alas, this answer doesn't include any information about _how_ such a thing happens. How can lines be added and then go completely missing with no record of corresponding deletions? A colleague and I just saw something similar today. It seemed to be caused by a bad merge, but there's no record in the history of where and when the lines disappeared. – Ryan Lundy Mar 01 '17 at 13:26
  • Yes the entire file history being lost can cause all kinds of confusion, because it can be lost anywhere withou you ever being aware of it. Tracking it down can take hours in some cases. – Jeremy Ray Brown Aug 29 '17 at 20:30
6

Related question; can I somehow find out, if there are other instances of stuff going bye-bye like this? I'm slightly worried ;)

Try git whatchanged. For instance,

git whatchanged --since="2 weeks ago" -- gitk

Show the changes during the last two weeks to the file gitk.

Prince John Wesley
  • 62,492
  • 12
  • 87
  • 94
  • 4
    I didn't know that one, thanks, but what I'm really looking for, is some way of detecting "evil merges" - that is, merge commits introducing changes, that are not in either branch merged. – Vonsild Jul 09 '13 at 07:32
  • What do you mean by *"to the file gitk"*? [gitk](https://git-scm.com/docs/gitk) launches a GUI program. Please respond by [editing (changing) your answer](https://stackoverflow.com/posts/17527497/edit), not here in comments (***without*** "Edit:", "Update:", or similar - the answer should appear as if it was written today). – Peter Mortensen Jun 07 '22 at 21:34
5

Apparently (see this question), git show is not the right tool to use to have a clear view of the changes introduced by a merge commit.

Use git diff. The merge commit has two parents:

*   8ac6131 (M) Merge branch 'B'
|\
| * 5a53959 (B) two
|
* 7cb5a06 (A) one

Use git diff A M and git diff B M to view the differences between the merge commit and either of its parent. You should see your missing function there.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
LeGEC
  • 46,477
  • 5
  • 57
  • 104
  • Tried this but, the code that disappeared at merge, doesn't show as deleted with diff. – Gringo Suave Jan 10 '19 at 01:31
  • @GringoSuave : after re-reading my answer, I thunk the '..' may have strange effects. Can you try with the edited answer ? – LeGEC Jan 10 '19 at 08:45
0

It turns out I was looking at two different folders (both on master) and forgot to pull the latest changes into one of them.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
gabn88
  • 781
  • 8
  • 23