Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does "git rebase" leave opposite sets of modifications in the stage and the working copy?

I'm using git-svn as an svn client. From time to time I encounter the following issue.

  1. I start with a couple of commits in my local git branch, a empty stage and a clean working copy.

  2. I type "git svn rebase" in windows command line to fetch the team's modifications and put my commit after them to keep a linear history (this is required to use git-svn)

  3. Everything goes fine, team's content is fetched and my commits are rebased after then, but...

    I end up with modifications in the working copy, and modified files in the stage, and the modifications of the working copy are the exact oposite of the modifications in the stage.

I Usually work around this by just unstaging everything that's in the stage, which reverts the modifications in the working copy, which is fine, but I would really like to understand what's happening here.

Question: Is that a bug, or is it something that I don't understand with git rebase?

Note: I had the issue while using "git svn fetch" and "git rebase" later.

Note: I use git on windows with a large svn repository (10000+ files, 150000+ revisions), and I also use git-extensions. Edit: I use it only explore the repository and commit. I do anything else from windows command line.

Edit: As requested by one of the comment, here are two screenshot to help understand the problem. The first is the content of the working copy, the second is the content of the stage. You can easily see the both are the exact oposite:

Working copy: enter image description here

Stage (reverts working copy modifications, very visual: same image, red and green are swapped): enter image description here

Edit: I just reproduced the issue in a very simple case: My commit modifies only one file, very few new commits were fetched during the "git svn rebase", and none of them affected the modified file. I checked with "gitk --all". It says exactly the same thing than git-extensions and "git status" Here is the output of gitk. We see from bottom to top:

  • The last 3 lines are the 3 commits tha were fetch when rebasing. None of them touches my file.
  • The 3rd line from top show my commit after rebase: it's all good, it adds what it's supposed to add and removes what it's supposed to remove.
  • The 2nd line shows the content of the index: it contains modifications that revert my commit
  • The 1st line shows the content of the working copy: it contains the same modifications that my commit does, IE reverts the modification in the index.

enter image description here

Edit: Here is the content of my .git dir after a "git svn rebase" where the problem occured:

17/02/2012  04:57                 0 ArmuazEm5Z
05/04/2012  02:28                 0 BeMzRLwWcu
06/11/2012  14:37                90 COMMIT_EDITMSG
01/11/2012  15:42               628 config
15/02/2012  04:21                73 description
16/02/2012  13:22                 0 fuMhUevkYu
05/11/2012  15:53         1 703 279 gitk.cache
05/07/2012  03:49                 0 gJfUbdRuG9
06/11/2012  14:42                23 HEAD
11/07/2012  03:14    <DIR>          hooks
21/02/2012  03:22                 0 II5HPacSJd
06/11/2012  14:42         5 439 960 index
15/10/2012  13:18    <DIR>          info
16/02/2012  08:16                 0 jerS1GtBYS
17/02/2012  04:57                 0 Kg64sq9pzS
15/02/2012  23:36                 0 lbe0yALJYy
15/10/2012  13:17    <DIR>          logs
19/10/2012  16:58    <DIR>          objects
06/11/2012  14:42                41 ORIG_HEAD
25/10/2012  11:02             2 795 packed-refs
05/07/2012  03:49                 0 PpxYa5z0Hc
02/11/2012  10:00    <DIR>          refs
15/02/2012  23:36                 0 sm6ociDGGF
06/11/2012  14:42    <DIR>          svn
21/02/2012  03:22                 0 vEqtL0Yiqd
05/04/2012  02:28                 0 VFwn3laTEV
16/02/2012  13:22                 0 XYoiLqY5BM
16/02/2012  08:16                 0 z9vL8lRT7t
              22 File(s)      7 146 889 bytes
               6 Dir(s)  54 105 219 072 bytes free

Edit: If you are interested in tracking this issue, I reported a bug on [email protected] mailing list with "[git-svn] [bug report] Index in strange state after git svn rebase" in the subject.

like image 365
Samuel Rossille Avatar asked Nov 01 '12 18:11

Samuel Rossille


People also ask

Does rebase keep changes?

After starting a rebase, Git creates an anonymous branch and starts applying commits to it. Since ours means "keep changes from the current branch", that current branch will be HEAD , which contains upstream and any changes already applied by rebase .

What happens when rebase?

The Rebase Option But, instead of using a merge commit, rebasing re-writes the project history by creating brand new commits for each commit in the original branch. The major benefit of rebasing is that you get a much cleaner project history. First, it eliminates the unnecessary merge commits required by git merge .

What can go wrong with rebase?

It is also very powerful, but sometimes things can go really wrong. One common issue is using git rebase when a branch is outdated and points to an old commit from master. Older branches can lead to a lot of conflicts, making rebase a nightmare.

Why you should never rebase in git?

Rebasing can be dangerous! Rewriting history of shared branches is prone to team work breakage. This can be mitigated by doing the rebase/squash on a copy of the feature branch, but rebase carries the implication that competence and carefulness must be employed.


1 Answers

This appears to be a bug. If your working directory and index are clean before a rebase, they should be clean after rebase; or you should get a merge conflict and the opportunity to clean it up and continue the rebase.

It looks like for some reason, your index is being left stale after applying your local modifications.

Basically, there are three main views of the current state of the repository. There is the HEAD commit, which is the state of the repository as of the last commit, and what your next commit will be a child of. This is being updated properly during your rebase; HEAD is now your local commit, rebased on top of what you got from the upstream repository.

There's the index, which is supposed to contain a view of what the state of your next commit will be. This seems to be where the problem is. After a successful rebase from a clean tree, the index should appear to have the same view of the repository as HEAD, but it appears to be getting a stale view, of what the upstream repository contains. It looks like it isn't being updated after applying your local patches on top of the upstream repository.

And there's your working copy; the actual files on your disk. For some reason, when you are doing the rebase, the head commit is being updated properly, and the working tree is being updated properly (or is being left alone), but the index is left in a state that refers to the origin commit that you are rebasing onto. This means that if you compare the index to your rebased commit, it looks like you have reverted your changes, and if you compare your working copy to your index, it looks like you have added them back again.

A few things to check:

  1. Can you show us the contents of your .git directory after such a problematic rebase? Just a list of the files at the top level of .git would be helpful. Actually, a full listing, including filenames, modification dates, and permissions might give a little more information.
  2. Are you using this over any kind of networked filesystem, or anything else odd? Networked filesystems sometimes have issues in which files will be left stale; I wonder if that is happening to you.
  3. What version of Git are you using?
like image 92
Brian Campbell Avatar answered Sep 20 '22 05:09

Brian Campbell