13

Our development team is using git and we've lost changes to files at least twice recently. We are using private Github repos.

In the current case, we can go back through the logs on Github and see some updates I made to a file. Later, another team member changed a different part of the file, and it appears to have destroyed my changes. I still have them locally.

Has else anybody experienced this? Any causes or solutions?

I don't think anybody is doing any rebasing or anything fancy - just pulling and pushing.

Nathan Long
  • 122,748
  • 97
  • 336
  • 451
  • 4
    how does the teammember get his changes committed and pushed up? I doubt git is 'losing' data. I think it is more likely that someone is doing something like not merging changes and and just taking their changes... – hvgotcodes Dec 15 '10 at 20:40
  • 3
    If you inspect each of the diffs between versions you will probably see the previous changes being reverted. This is the most common cause of data loss caused by people making bad commits. A git revision visualizer or graphical git front-end can help track these down. – tadman Dec 15 '10 at 20:43
  • @hvgotcodes - He says he does "commit, pull, push." So you're saying that when there are merge conflicts, he may just be saying "I win?" – Nathan Long Dec 15 '10 at 20:45
  • `pull --rebase` does a rebase, and a regular `pull` does a merge. Maybe it's just a merge conflict? – P Shved Dec 15 '10 at 20:53

9 Answers9

9

I would like to add my few words. I lately noticed very strange behavior in git. My team had big problems because of that. I don't know how it happened but it seems that history in my repo is inconsistent.

Little illustration:

commit XXXXXXXX:

Line "bar" was added to file foo.

...work in progress...

lots of commits later(let's say about 100):

Line "bar" no longer exists in this file!!

Investigation:

1.I inspected history of file with:

git log foo and gitk foo

I even compared consecutive blobs from every commit with external tool(gvimdiff). It's interesting thing that I found two commits(let's call them YYY and ZZZ). Blob of file foo from commit YYY consisted "bar" but blob from ZZZ didn't.
When I inspected commitdiffs of those commits with gitk(and gitweb) I noticed that there is no operation of removing line "bar" in ZZZ. Is it possible that there was some commit in between and dissolved in thin air?
Or maybe commit ZZZ just removed my line and diff tool embedded in git(or gitk) is broken?

2.I searched for commits which could delete this line with "git log -S", something like:

git log -S'bar' -- foo

It turns out that this line was never deleted. As a matter of fact it was added two times. First time when it was introducted to project and second time when it was added again as an urgent bugfix.

I really like using git and even persuaded few friends to use it but if that kind of magic continue to happen, I will have to start searching for alternatives.

shark555
  • 2,562
  • 1
  • 20
  • 10
7

Similar thing happened to my team too.

Lesson learned: when you pull, you should be careful about merge conflicts. If there're conflicts on pull, git doesn't commit merged changes into your local repo and you must do this after you resolve the conflict. Otherwise, while pushing, you will overwrite remote repo with your local copy NOT containing changes of people did in remote before you pulled. This explains some 'strange files' you might see uncommitted but you're sure that's not your changes - this is indication of a merge conflict on 'pull' and - again - you must commit these changes to local after you resolve the conflict and then push to remote.

If you have no conflicts in merge on pull - no issues with lost changes arise. Because git fetches, merges and commits to your local copy, and 'push' then propagates these merged changes to remote.

ikaschenko
  • 111
  • 2
  • 5
  • I'm not completely certain of this but, I think that after a merge conflict, if you only commit the conflicted files (or any other subset of the changes), the rest of the changes will be lost. That's most likely what happened in my case, a coworker messed it up with the merge. – lordscales91 May 10 '18 at 08:30
2

I have had similar issues where in the general log I can see the changes I made to a file, but when I check the specific log for the file, those changes don't show up, only those of my coworker. I am pretty sure this is because my coworker messed up the merge somehow... But I still wish this would show up in the log.

Speedy
  • 326
  • 2
  • 7
2

While I can't speak to your specific issue, what I can say is that yesterday I experienced something very similar. I had a designer mucking around with some URLs in the code, and updating some images in an iPhone app I was finishing up on, and didn't tell me about it. I pushed my changes I had made which touched on some of these files too (different spots however), and it rejected as non-local fast forward. So I pulled, got conflicts, resolved them and pushed. Problem solved. However, I did undo his code changes in the process.

One thing I have recently added to my workflow due to a problem very similar to this I experienced yesterday, on a github private repo; is to stash my changes I'm about to commit, pull from the repo, and apply my stash. Should there be conflicts, resolve those, then push.

jer
  • 20,094
  • 5
  • 45
  • 69
  • Nice idea, but your workflow means that you can't commit multiple times between pull/push cyles. Someone told me you can use "git pull --rebase" to solve the same problem, but I don't know what implications that has on the history and am suspicious of rebasing in general (at least right now, maybe because I don't understand it). – Nathan Long Dec 15 '10 at 20:47
  • P.S. - I'm not saying you're wrong, I'm just saying there's a downside. :) – Nathan Long Dec 15 '10 at 20:53
  • @jer: I think your solution is basically the same as rebasing – Grimace of Despair Feb 26 '14 at 08:14
1

My guess is that there are different configuration among committers, perhaps someone is missing an autocrlf configuration.

Git somehow considers completely different two revisions of the same file, thus overwriting the old one with newer changes from another branch.

If a three-way merge (default recursive one) finds two completely different childs (ie because of CRLF misconfiguration) the merged result will be the most recent one, with no conflicts.

Shine
  • 3,788
  • 1
  • 36
  • 59
1

I managed to reproduce an instance of this in Visual Studio.

In the conflict resolution screen in VS, once you finish picking the changes from both branches, if you don't manually save the file before clicking "accept merge", it just uses the left (old) version without prompting for lost changes, as it would in other circumstances.

user5226582
  • 1,946
  • 1
  • 22
  • 37
0

We had the same issue: Dev A made a change. Dev B made a change to something else. After Dev B pushed his changes the change that Dev A made "vanished." The change that Dev B made was weeks ago but it seemed no one had noticed the loss of Dev A's changes until now.

The real reason the change "vanished" was that the tool we were using to view history (TFS) was showing an incorrect version of history. When we looked with different tools (SmartGit and SourceTree) we saw what really happened: Someone had overwritten the change while trying to fix a merge conflict and the overwrite was there in plain view.

So, it was not git that was losing changes, it was the tool we were using giving us a false view of history. Just something to look out for.

We've been using git for a year now and 99% of the time that something has "gone wrong" with git, it was actually caused by someone who did not really understand git. The only time it "was git" was a CRLF issue, but really that was because we didn't know git well enough and (thanks to SO) it was easy to handle.

So, always look carefully and you'll probably find the problem boils down to someone not understanding git and doing something they shouldn't have.

grahamesd
  • 4,773
  • 1
  • 27
  • 27
0

In my case, I stashed my changes to work on an emergency bugfix and simply forgot to unstash and commit them

mohas
  • 1,911
  • 1
  • 16
  • 20
0

Had this issue and found the following snippet helped in analysis:

git for-each-ref --sort=-committerdate refs/heads/ --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate)%(color:reset))'

This allows one see the last commit to the repo (sort=-committerdate) in all branches (refs/heads/).

  • sample observation:

    feature/blah_a - 9e492d9 - done b4 but committed l8r - (Sat Sep 15 14:29:53 2020)
    feature/blah_b - f98db7a - something - (Sat Sep 26 11:38:42 2020)
    feature/blah_c - 4ab7ee7 - somethang - (Tue Sep 24 17:38:25 2020)
    

    The reader will notice that feature/blah_a predates others but was merged later causing 'loss' of intervening check-ins.

Another 'easy to remember' snippet is:

git log -20 --date=iso --pretty=format:'%cd %h %d'

While its output is terse, it gives a quick snapshot indicating if HEAD commit predates later references.

Code Maverick
  • 326
  • 2
  • 6