{"thread":{"id":"23717","subject":"Problem with git merge/rebase with conflicts","startedAt":"2010-05-06T10:06:04Z","lastAt":"2010-05-08T05:52:02Z","messageCount":5,"participants":["Eli Barzilay","Junio C Hamano","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"141063","messageId":"19426.38028.501924.921359@winooski.ccs.neu.edu","threadId":"23717","inReplyTo":null,"subject":"Problem with git merge/rebase with conflicts","fromName":"Eli Barzilay","fromEmail":"eli@barzilay.org","sentAt":"2010-05-06T10:06:04Z","receivedAt":"2010-05-06T10:06:04Z","isPatch":false,"sender":{"key":"eli@barzilay.org","avatar":"https://avatars.githubusercontent.com/u/185905?v=4"},"body":"I'm writing about merging and rebasing with conflicts, and there's\nsomething weird with it -- after this setup:\n\n  mkdir /tmp/r1; cd /tmp/r1; git init\n  echo foo > file; git add file; git commit -m first\n  cd /tmp; git clone r1 r2\n  cd /tmp/r1; echo abc > file; git commit -m abc file\n  cd /tmp/r2; echo xyz > file; git commit -m xyz file\n  git fetch\n\n1. I get this:\n\n     $ git merge origin\n     ...CONFLICT...\n     $ git status -s\n     UU file\n     $ echo xyz > file\n     $ git add file\n     $ git status -s\n\n   and there's nothing -- it's all clean after that `add', without\n   committing and without anything said.  If this is intentional, it\n   would be nice if there was some message from `git add'...  And it\n   would also be nice if I'd seen it mentioned anywhere, but\n   practically everything I've read said the same: `git add' and then\n   `git commit', no mention of that second step being optional.\n\n2. I have some other sample repository that exhibits the behavior with\n   the \"resolution\" going the other way, but here -- starting from the\n   same setup:\n\n     $ git merge origin\n     ...CONFLICT...\n     $ echo abc > file\n     $ git add file\n     $ git status -s\n     M  file\n     $ git commit\n     ...get an editor without the conflict resolution template thing...\n     $ git log --graph --all --oneline\n     * 2d3744b Huh?\n     * 98c46da xyz\n     | * 4744b19 abc\n     |/  \n     * c8915c2 first\n\n   This looks like I never did any merge.\n\n     $ git merge origin\n     Merge made by recursive.\n     $ git log --graph --all --oneline\n     *   94e69e9 Merge remote branch 'origin'\n     |\\  \n     | * 4744b19 abc\n     * | 2d3744b Huh?\n     * | 98c46da xyz\n     |/  \n     * c8915c2 first\n\n   And this looks even more wrong...\n\n3. Again, starting from the same setup:\n\n     $ git rebase origin\n     ...CONFLICT...\n     $ git status -s\n     UU file\n     $ echo abc > file\n     $ git add file\n     $ git status -s\n                       <- nothing\n     $ git rebase --continue\n     Applying: xyz\n     No changes - did you forget to use 'git add'?\n\n   which is probably related to the above.  I could use --skip, but\n   now that I edited it manually I can't remember that --skip does\n   what I already did.\n\n-- \n          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:\n                    http://barzilay.org/                   Maze is Life!\n"},{"id":"141078","messageId":"7v8w7wj134.fsf@alter.siamese.dyndns.org","threadId":"23717","inReplyTo":"19426.38028.501924.921359@winooski.ccs.neu.edu","subject":"Re: Problem with git merge/rebase with conflicts","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-05-06T19:13:03Z","receivedAt":"2010-05-06T19:13:03Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eli Barzilay <eli@barzilay.org> writes:\n\n> 1. I get this:\n> 3. Again, starting from the same setup:\n\nI don't have time to look at the second one, but these are quite obvious\nand natural.  \"status\" in these cases notices that you haven't made any\nchange relative to HEAD (in either the index nor in the working tree)\nafter all, and that is what is being reported.\n"},{"id":"141087","messageId":"19427.10872.708654.433450@winooski.ccs.neu.edu","threadId":"23717","inReplyTo":"7v8w7wj134.fsf@alter.siamese.dyndns.org","subject":"Re: Problem with git merge/rebase with conflicts","fromName":"Eli Barzilay","fromEmail":"eli@barzilay.org","sentAt":"2010-05-06T20:45:44Z","receivedAt":"2010-05-06T20:45:44Z","isPatch":false,"sender":{"key":"eli@barzilay.org","avatar":"https://avatars.githubusercontent.com/u/185905?v=4"},"body":"On May  6, Junio C Hamano wrote:\n> Eli Barzilay <eli@barzilay.org> writes:\n> \n> > 1. I get this:\n> > 3. Again, starting from the same setup:\n> \n> I don't have time to look at the second one,\n\n(FWIW, I can't recreate it now -- very weird since when I sent that\nmessage it was definitely repeatable.)\n\n\n> but these are quite obvious and natural.  \"status\" in these cases\n> notices that you haven't made any change relative to HEAD (in either\n> the index nor in the working tree) after all, and that is what is\n> being reported.\n\nYes, I agree that they're doing \"obviously\" doing the right thing, but\nI don't think that they're natural enough...  I'm not saying that it's\ndoing something broken, just that some of the interface (=> printouts)\ncould eliminate surprises.  Here are some problems that I've seen,\nIMO, some of them are indications that this is not natural.  I'll\nprefix each one with the false belief that I had (and that I didn't\nsee any text that would correct it...).\n\n1. False belief: After you edit and `git add' a file, you will need to\n   commit it to make the change part of your history.\n\n   Obvious counter example: edit a file and `git add' it; undo the\n   edit in the file and `git add' again -- you now have nothing to\n   commit.\n\n   A way that I think will solve this: make `git add' notify you that\n   the changes that you just added canceled earlier changes and you're\n   back to a clean state.\n\n2. False belief: If you have a completely clear working directory and\n   index, then there's nothing for you to commit.  (At least without\n   forcing an empty commit.)\n\n   Counter example: run this (simplified example)\n\n     rm -rf /tmp/test; mkdir /tmp/test; cd /tmp/test; git init\n     echo foo > file; git add file; git commit -m first\n     git branch a-branch;   echo abc > file; git commit -m abc file\n     git checkout a-branch; echo xyz > file; git commit -m xyz file\n     git merge master; echo xyz > file; git add file\n     git status\n\n   That last `status' will happily tell you that \"nothing to commit\n   (working directory clean)\" -- but `git commit' *will* commit the\n   merge.\n\n   A way that I think will solve this: clearly there is somewhere\n   something that makes the commit possible (probably .git/MERGE*\n   files) -- so make `git status' inspect these and say something\n   about it instead of saying that there's nothing to commit.  (The\n   other option would be to make `git add' clear out the merge state\n   too, but this is probably very broken.)\n\n2a. A related problem: usually when I try to checkout a different\n   branch when I have changes, git barfs at me.  But after that script\n   is run, I can `git checkout master' with no errors or warnings, and\n   the merge commit is gone.  It looks like checkout is even careful\n   enough to remove the .git/MERGE* files, so making it barf (or at\n   least spit out some warning) is probably easy...\n\n3. False belief: if your working directory and your index are dirty,\n   then there *is* something for you to commit.\n\n   Obvious counter example: edit a file and `git add' it; undo the\n   edit in the file but *don't* `git add' again -- `git status -s'\n   will now say:\n\n     MM file\n\n   And now:\n\n     $ git commit .\n     # On branch master\n     nothing to commit (working directory clean)\n\n   but the status is still not cleared.  Trying to checkout a\n   different branch gives me the barf.\n\n   A way that I think will solve this: make `git commit <path>' add\n   the paths before committing -- and if `add' says something, it will\n   say that here and clarify what happened.  But this is probably too\n   much of a change, so alternatively `git commit' would notice that\n   there was nothing to commit because of this state, and `add' the\n   right files to clear out the status (after saying something about\n   it).\n\n4. `git rebase' issues -- I've sent a separate message about that, and\n   IMO adding those notes to what rebase says would clear up most of\n   the confusion, and probably if the above are done then it will also\n   help rebase to be more robust.\n\n-- \n          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:\n                    http://barzilay.org/                   Maze is Life!\n"},{"id":"141227","messageId":"20100508052036.GF14998@coredump.intra.peff.net","threadId":"23717","inReplyTo":"19427.10872.708654.433450@winooski.ccs.neu.edu","subject":"Re: Re: Problem with git merge/rebase with conflicts","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-05-08T05:20:36Z","receivedAt":"2010-05-08T05:20:36Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, May 06, 2010 at 04:45:44PM -0400, Eli Barzilay wrote:\n\n> 1. False belief: After you edit and `git add' a file, you will need to\n>    commit it to make the change part of your history.\n> \n>    Obvious counter example: edit a file and `git add' it; undo the\n>    edit in the file and `git add' again -- you now have nothing to\n>    commit.\n> \n>    A way that I think will solve this: make `git add' notify you that\n>    the changes that you just added canceled earlier changes and you're\n>    back to a clean state.\n\nI don't understand how this is a false belief. You _haven't_ made\nanything a part of your history. It was already there, and you've done\nnothing to the history.\n\nBut I thought your original question started out with a conflicted\nmerge:\n\n>   mkdir /tmp/r1; cd /tmp/r1; git init\n>   echo foo > file; git add file; git commit -m first\n>   cd /tmp; git clone r1 r2\n>   cd /tmp/r1; echo abc > file; git commit -m abc file\n>   cd /tmp/r2; echo xyz > file; git commit -m xyz file\n>   git fetch\n>   git merge origin\n>   echo xyz > file\n>   git add file\n>   git status -s\n\nIn that case you _do_ have to commit, or your history will not contain\nthe merge! Even though you happened to reject the other sides changes,\nyou still want to generate a merge commit showing that in your history\nyou have examined and rejected the other side's changes.\n\nThe only failing here, if any, is that \"git status\" does not say \"you\nare in the middle of a merge, and should commit it\".\n\n> 2. False belief: If you have a completely clear working directory and\n>    index, then there's nothing for you to commit.  (At least without\n>    forcing an empty commit.)\n> \n>    Counter example: run this (simplified example)\n> \n>      rm -rf /tmp/test; mkdir /tmp/test; cd /tmp/test; git init\n>      echo foo > file; git add file; git commit -m first\n>      git branch a-branch;   echo abc > file; git commit -m abc file\n>      git checkout a-branch; echo xyz > file; git commit -m xyz file\n>      git merge master; echo xyz > file; git add file\n>      git status\n> \n>    That last `status' will happily tell you that \"nothing to commit\n>    (working directory clean)\" -- but `git commit' *will* commit the\n>    merge.\n\nYeah, probably it should detect the presence of .git/MERGE_HEAD and\nprint a different message.\n\n> 3. False belief: if your working directory and your index are dirty,\n>    then there *is* something for you to commit.\n> \n>    Obvious counter example: edit a file and `git add' it; undo the\n>    edit in the file but *don't* `git add' again -- `git status -s'\n>    will now say:\n> \n>      MM file\n> \n>    And now:\n> \n>      $ git commit .\n>      # On branch master\n>      nothing to commit (working directory clean)\n> \n>    but the status is still not cleared.  Trying to checkout a\n>    different branch gives me the barf.\n\nI think you misunderstand how \"git commit .\" works. It already means\n\"git add . && git commit\". So you are actually _removing_ the thing to\ncommit in the first step. Running \"git commit\" would work.\n\nWhich is what you suggest:\n\n>    A way that I think will solve this: make `git commit <path>' add\n>    the paths before committing -- and if `add' says something, it will\n>    say that here and clarify what happened.  But this is probably too\n>    much of a change, so alternatively `git commit' would notice that\n>    there was nothing to commit because of this state, and `add' the\n>    right files to clear out the status (after saying something about\n>    it).\n\nExcept that I guess you want the add process to say \"the thing you added\nis the same as HEAD, so you just reverted the original thing you added\".\nPersonally I would find such a notification annoying.\n\n-Peff\n"},{"id":"141233","messageId":"19428.64514.817261.34710@winooski.ccs.neu.edu","threadId":"23717","inReplyTo":"20100508052036.GF14998@coredump.intra.peff.net","subject":"Re: Re: Problem with git merge/rebase with conflicts","fromName":"Eli Barzilay","fromEmail":"eli@barzilay.org","sentAt":"2010-05-08T05:52:02Z","receivedAt":"2010-05-08T05:52:02Z","isPatch":false,"sender":{"key":"eli@barzilay.org","avatar":"https://avatars.githubusercontent.com/u/185905?v=4"},"body":"On May  8, Jeff King wrote:\n> On Thu, May 06, 2010 at 04:45:44PM -0400, Eli Barzilay wrote:\n> \n> > 1. False belief: After you edit and `git add' a file, you will\n> >    need to commit it to make the change part of your history.\n> > \n> >    Obvious counter example: edit a file and `git add' it; undo the\n> >    edit in the file and `git add' again -- you now have nothing to\n> >    commit.\n> > \n> >    A way that I think will solve this: make `git add' notify you\n> >    that the changes that you just added canceled earlier changes\n> >    and you're back to a clean state.\n> \n> I don't understand how this is a false belief. You _haven't_ made\n> anything a part of your history. It was already there, and you've\n> done nothing to the history.\n\nWell, the false belief here is following every text that (very\nreasonably) tells you that you should `git add' the file and then `git\ncommit' it.  Obviously, with a cooked example like that things are\nmade very clear -- but what if I worked on something for a while\n(adding stuff to the index as I go), and missed the fact that the file\nis eventually at exactly where it started?  Even with this it's\nprobably not too bad as is, but with merges it gets even more\npotential to be confusing.  In any case, I'm not saying that anything\nis wrong -- just that it would be nice if `git add' told me about it,\nso I can never see a transcript that ends with:\n\n  $ git add foo\n  $ git commit\n  ... nothing to commit\n\nsince that canceling add will tell me explicitly that this addition\ngot things back to a state of having no changes.  (And I don't see any\nharm in that -- if you want to explicitly revert things back you'd use\nreset or something, so this change is something that you'd only see if\nyou were confused as above.)\n\n\n> But I thought your original question started out with a conflicted\n> merge:\n> \n> >   mkdir /tmp/r1; cd /tmp/r1; git init\n> >   echo foo > file; git add file; git commit -m first\n> >   cd /tmp; git clone r1 r2\n> >   cd /tmp/r1; echo abc > file; git commit -m abc file\n> >   cd /tmp/r2; echo xyz > file; git commit -m xyz file\n> >   git fetch\n> >   git merge origin\n> >   echo xyz > file\n> >   git add file\n> >   git status -s\n> \n> In that case you _do_ have to commit, or your history will not\n> contain the merge! Even though you happened to reject the other\n> sides changes, you still want to generate a merge commit showing\n> that in your history you have examined and rejected the other side's\n> changes.\n> \n> The only failing here, if any, is that \"git status\" does not say\n> \"you are in the middle of a merge, and should commit it\".\n\nYes, that was exactly the conclusion of my following point.  Well,\neven more than that -- if `git add' will tell you about getting into a\nclean state, then you'd get this for the first case above:\n\n  $ git add foo\n  note: this addition canceled out all changes\n  $ git commit\n  ... nothing to commit         # <-- this is obvious now\n  $ git status -s\n                                # <-- as is the lack of output here\n\nand for the merge case, `git add' could note that, in addition to a\nclean state, you still have a merge to finish, so it could say this:\n\n  $ git merge blah\n  ...\n  $ git add foo\n  note: this addition canceled out all changes,\n  but you still have a pending merge to commit\n  $ git status -s\n  (merge pending)               # <-- this is my item#2 suggestion\n\n\n> > 3. False belief: if your working directory and your index are dirty,\n> >    then there *is* something for you to commit.\n> > \n> >    Obvious counter example: edit a file and `git add' it; undo the\n> >    edit in the file but *don't* `git add' again -- `git status -s'\n> >    will now say:\n> > \n> >      MM file\n> > \n> >    And now:\n> > \n> >      $ git commit .\n> >      # On branch master\n> >      nothing to commit (working directory clean)\n> > \n> >    but the status is still not cleared.  Trying to checkout a\n> >    different branch gives me the barf.\n> \n> I think you misunderstand how \"git commit .\" works. It already means\n> \"git add . && git commit\". So you are actually _removing_ the thing to\n> commit in the first step. Running \"git commit\" would work.\n> \n> Which is what you suggest:\n> \n> >    A way that I think will solve this: make `git commit <path>'\n> >    add the paths before committing -- and if `add' says something,\n> >    it will say that here and clarify what happened.  But this is\n> >    probably too much of a change, so alternatively `git commit'\n> >    would notice that there was nothing to commit because of this\n> >    state, and `add' the right files to clear out the status (after\n> >    saying something about it).\n> \n> Except that I guess you want the add process to say \"the thing you\n> added is the same as HEAD, so you just reverted the original thing\n> you added\".\n\nYes.\n\n\n> Personally I would find such a notification annoying.\n\nIsn't this something that you'd never do intentionally?  I'm not\ntalking about doing this for any specific file in the commit (actually\nthe `add' part of the commit) -- I'm suggesting that it will say that\nonly if the result of adding stuff made the following commit do\nnothing.  So this message would only annoy you if you've done some\nchanges and added them, then you edit the files back to the original\nstate, and then use `git add' or `git commit <paths>' (!) to add the\nchanges so you're back to a clean state.  This sounds like a very odd\nway of undoing changes (especially with git that gives me about 200\nways to undo changes more directly...).\n\n-- \n          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:\n                    http://barzilay.org/                   Maze is Life!\n"}]}