gitgit-rebasegit-update-ref

why does git update-ref also stage the files between old and new commits?


I've a script that refreshes the index to latest commit but git also stages the files changed between the old and new commits which I don't expect.

Steps are as following :

Fetch latest changes from remote repo

git fetch origin master 

Git references looks like the following now :

❯ git show-ref | grep -E "master$"
79ba3075fcf4263273dfd222cdd7773624c80913 refs/heads/master
688e154cf3bc04198b401789e75e4d496f7344b6 refs/remotes/gerrit/master
c87fb2b5bc576a23e9af600745210d7b9cab30d2 refs/remotes/origin/master

Update the local reference with the latest remote refernce.

git update-ref refs/heads/master refs/remotes/origin/master

Now the local reference is updated too which we expected

❯ git show-ref | grep -E "master$"
c87fb2b5bc576a23e9af600745210d7b9cab30d2 refs/heads/master
688e154cf3bc04198b401789e75e4d496f7344b6 refs/remotes/gerrit/master
c87fb2b5bc576a23e9af600745210d7b9cab30d2 refs/remotes/origin/master

Now I expected the git status to report that local branch is upto date with remote branch since the local reference is updated as of remote reference. But I see that git also staged the files which were changed between the old and new commits.

git status  | wc -l         
3196

I don't understand why would that happen. My current branch is same "master". I did not get any clue over the web or in the command manual. Any idea what could be the reason ?


Solution

  • The problem here is that you are assuming that you would end up with the working tree and the index looking exactly like the new position of the branch that you are working on and adjusting.

    If you are working on branch-X and you adjust the reference of branch-Y, then when you run git checkout branch-Y git will move the pointer of HEAD to that branch, and make index look like the commit pointed to by branch-Y and adjust the working tree accordingly.

    However, if you are on branch-Y and you move that branch to a different commit (without messing with the index and the working tree, just like what you would expect update-ref to do), git would have to consider (as it always does) the differences between index and the commit that the branch is now pointing to (which can be A LOT, because the index will look much like the previous commit the branch was pointing to) and the differences between index and the working tree.... and all of that simply because update-ref does not mess up with index or the working tree.

    If you wanted to get the working tree and the index to also resemble the content of the new position of the branch, you should consider using git reset --hard instead to do the 3 things:

    Use with care as git reset --hard will get rid of any uncommitted changes that were laying around the index or the working tree.