Git is losing history/contents on individual files
Asked Answered
U

4

8

I work in a small company and our Git repo is a little messed up. I just did a git pull and my changes made earlier today are gone!

When I work on HEAD on the master branch, git log shows my last commit b94940c63ef965ce45b0d64ccfba4359134d2552 in its history.

Now if I do git log filename for the problematic file that lost my changes, that commit is not shown (only shows an earlier commit).

Performing git log --follow filename, my commit b94940c63ef965ce45b0d64ccfba4359134d2552 is shown as most recent.

And sure enough if I do:

git checkout b94940c63ef965ce45b0d64ccfba4359134d2552
git log filename

then the commit is shown and my changes are in the file!

In other words, the commit I made is shown in the branch history (blocking a branch merge), but individual modified files do not have that commit in their history! (unless I explicitly checkout that commit).

Questions:

  1. How on earth did this happen?

  2. How do I fix it? (We have problems with multiple files in our repo)

Unusual answered 5/8, 2011 at 0:34 Comment(0)
U
5

Alright figured out the problem. When a coworker pulled, he got some conflicts. Rather than resolving, he git reset every staged file. This was akin to doing a git checkout old_version on individual old files. So HEAD on the master ended up referring to some files that had old_version.

Now I'm manually restoring what he blew out.

Moral of story: Modifying git operations (checkout, reset, etc.) on individual files are quite dangerous.

Unusual answered 5/8, 2011 at 2:42 Comment(2)
That's not really the moral. The moral is: "Learn to resolve merge conflicts." It applies to any VCS, and it seems to be the least-practiced skill among developers based on how many problems there are surrounding it.Glennglenna
Couldn't agree more, @Ryan, and the problem is often prolonged by people "manually restoring what he blew out" instead of reverting the change and making him do the merge properly.Hispania
G
1

This should be just a comment, but it would be hard to read. After checking out master:

git checkout master

what's the output of

git status

and

git whatchanged -m -p <path>

and

git log --graph --oneline b94940c63ef965ce45b0d64ccfba4359134d2552..master

?

Glennglenna answered 5/8, 2011 at 2:0 Comment(1)
Note for future commenters: whatchanged gets diff from git log --followUnusual
N
0

First of all, you should get a grip on what the Git commands do and what data is stored in the repository.

  • Get a history visualization tool like Giggle or Gitk to see your commit history and to see what commit is based on what commit.

  • git pull does two things: It retrieves the new commits from the remote repository, and it merges the head of the remote repository with your current head (in your current branch).

So in light of that, you may want to be more careful in the future. Instead of using git pull, you can do git fetch and manually merge what needs to be merged. That way you have control over what edits you are making.

As for your current situation, I don't think Git is losing data. You said that your file is still in the history. So now you will probably need to do some creative resets (reverting to old versions) or patches (possibly manually) to get your project files into the state that you want them to be.

Numerate answered 5/8, 2011 at 0:53 Comment(1)
Thanks for the advice on Giggle and Gitk. They are useful, but only telling me the same the console shows; the branch has correct history - the file does not. Somehow the files are on the wrong versions. Fortunately, there is no data loss, so I can do the resets. But I'm just worried that something else is going on (and things will break again really soon) - which is why I want to know how things got this way.Unusual
B
0

You can actually use this bash script in the folder you want to see which files that might have lost their commits:

#!/bin/zsh
for f in $(find . -name '*.php')
do
	follow=$(git log --oneline -1 --pretty=format:"%h" -- $f)
	log=$(git log --follow --oneline -1 --pretty=format:"%h" -- $f)
	
	if [ $log != $follow ]; then
  		echo "follow $follow , log $log => $f"
  	fi

done
Bart answered 31/3, 2016 at 11:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.