git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Problem with git merge/rebase with conflicts
@ 2010-05-06 10:06 Eli Barzilay
  2010-05-06 19:13 ` Junio C Hamano
  0 siblings, 1 reply; 5+ messages in thread
From: Eli Barzilay @ 2010-05-06 10:06 UTC (permalink / raw)
  To: git

I'm writing about merging and rebasing with conflicts, and there's
something weird with it -- after this setup:

  mkdir /tmp/r1; cd /tmp/r1; git init
  echo foo > file; git add file; git commit -m first
  cd /tmp; git clone r1 r2
  cd /tmp/r1; echo abc > file; git commit -m abc file
  cd /tmp/r2; echo xyz > file; git commit -m xyz file
  git fetch

1. I get this:

     $ git merge origin
     ...CONFLICT...
     $ git status -s
     UU file
     $ echo xyz > file
     $ git add file
     $ git status -s

   and there's nothing -- it's all clean after that `add', without
   committing and without anything said.  If this is intentional, it
   would be nice if there was some message from `git add'...  And it
   would also be nice if I'd seen it mentioned anywhere, but
   practically everything I've read said the same: `git add' and then
   `git commit', no mention of that second step being optional.

2. I have some other sample repository that exhibits the behavior with
   the "resolution" going the other way, but here -- starting from the
   same setup:

     $ git merge origin
     ...CONFLICT...
     $ echo abc > file
     $ git add file
     $ git status -s
     M  file
     $ git commit
     ...get an editor without the conflict resolution template thing...
     $ git log --graph --all --oneline
     * 2d3744b Huh?
     * 98c46da xyz
     | * 4744b19 abc
     |/  
     * c8915c2 first

   This looks like I never did any merge.

     $ git merge origin
     Merge made by recursive.
     $ git log --graph --all --oneline
     *   94e69e9 Merge remote branch 'origin'
     |\  
     | * 4744b19 abc
     * | 2d3744b Huh?
     * | 98c46da xyz
     |/  
     * c8915c2 first

   And this looks even more wrong...

3. Again, starting from the same setup:

     $ git rebase origin
     ...CONFLICT...
     $ git status -s
     UU file
     $ echo abc > file
     $ git add file
     $ git status -s
                       <- nothing
     $ git rebase --continue
     Applying: xyz
     No changes - did you forget to use 'git add'?

   which is probably related to the above.  I could use --skip, but
   now that I edited it manually I can't remember that --skip does
   what I already did.

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Problem with git merge/rebase with conflicts
  2010-05-06 10:06 Problem with git merge/rebase with conflicts Eli Barzilay
@ 2010-05-06 19:13 ` Junio C Hamano
  2010-05-06 20:45   ` Eli Barzilay
  0 siblings, 1 reply; 5+ messages in thread
From: Junio C Hamano @ 2010-05-06 19:13 UTC (permalink / raw)
  To: Eli Barzilay; +Cc: git

Eli Barzilay <eli@barzilay.org> writes:

> 1. I get this:
> 3. Again, starting from the same setup:

I don't have time to look at the second one, but these are quite obvious
and natural.  "status" in these cases notices that you haven't made any
change relative to HEAD (in either the index nor in the working tree)
after all, and that is what is being reported.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Problem with git merge/rebase with conflicts
  2010-05-06 19:13 ` Junio C Hamano
@ 2010-05-06 20:45   ` Eli Barzilay
  2010-05-08  5:20     ` Jeff King
  0 siblings, 1 reply; 5+ messages in thread
From: Eli Barzilay @ 2010-05-06 20:45 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

On May  6, Junio C Hamano wrote:
> Eli Barzilay <eli@barzilay.org> writes:
> 
> > 1. I get this:
> > 3. Again, starting from the same setup:
> 
> I don't have time to look at the second one,

(FWIW, I can't recreate it now -- very weird since when I sent that
message it was definitely repeatable.)


> but these are quite obvious and natural.  "status" in these cases
> notices that you haven't made any change relative to HEAD (in either
> the index nor in the working tree) after all, and that is what is
> being reported.

Yes, I agree that they're doing "obviously" doing the right thing, but
I don't think that they're natural enough...  I'm not saying that it's
doing something broken, just that some of the interface (=> printouts)
could eliminate surprises.  Here are some problems that I've seen,
IMO, some of them are indications that this is not natural.  I'll
prefix each one with the false belief that I had (and that I didn't
see any text that would correct it...).

1. False belief: After you edit and `git add' a file, you will need to
   commit it to make the change part of your history.

   Obvious counter example: edit a file and `git add' it; undo the
   edit in the file and `git add' again -- you now have nothing to
   commit.

   A way that I think will solve this: make `git add' notify you that
   the changes that you just added canceled earlier changes and you're
   back to a clean state.

2. False belief: If you have a completely clear working directory and
   index, then there's nothing for you to commit.  (At least without
   forcing an empty commit.)

   Counter example: run this (simplified example)

     rm -rf /tmp/test; mkdir /tmp/test; cd /tmp/test; git init
     echo foo > file; git add file; git commit -m first
     git branch a-branch;   echo abc > file; git commit -m abc file
     git checkout a-branch; echo xyz > file; git commit -m xyz file
     git merge master; echo xyz > file; git add file
     git status

   That last `status' will happily tell you that "nothing to commit
   (working directory clean)" -- but `git commit' *will* commit the
   merge.

   A way that I think will solve this: clearly there is somewhere
   something that makes the commit possible (probably .git/MERGE*
   files) -- so make `git status' inspect these and say something
   about it instead of saying that there's nothing to commit.  (The
   other option would be to make `git add' clear out the merge state
   too, but this is probably very broken.)

2a. A related problem: usually when I try to checkout a different
   branch when I have changes, git barfs at me.  But after that script
   is run, I can `git checkout master' with no errors or warnings, and
   the merge commit is gone.  It looks like checkout is even careful
   enough to remove the .git/MERGE* files, so making it barf (or at
   least spit out some warning) is probably easy...

3. False belief: if your working directory and your index are dirty,
   then there *is* something for you to commit.

   Obvious counter example: edit a file and `git add' it; undo the
   edit in the file but *don't* `git add' again -- `git status -s'
   will now say:

     MM file

   And now:

     $ git commit .
     # On branch master
     nothing to commit (working directory clean)

   but the status is still not cleared.  Trying to checkout a
   different branch gives me the barf.

   A way that I think will solve this: make `git commit <path>' add
   the paths before committing -- and if `add' says something, it will
   say that here and clarify what happened.  But this is probably too
   much of a change, so alternatively `git commit' would notice that
   there was nothing to commit because of this state, and `add' the
   right files to clear out the status (after saying something about
   it).

4. `git rebase' issues -- I've sent a separate message about that, and
   IMO adding those notes to what rebase says would clear up most of
   the confusion, and probably if the above are done then it will also
   help rebase to be more robust.

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Re: Problem with git merge/rebase with conflicts
  2010-05-06 20:45   ` Eli Barzilay
@ 2010-05-08  5:20     ` Jeff King
  2010-05-08  5:52       ` Eli Barzilay
  0 siblings, 1 reply; 5+ messages in thread
From: Jeff King @ 2010-05-08  5:20 UTC (permalink / raw)
  To: Eli Barzilay; +Cc: Junio C Hamano, git

On Thu, May 06, 2010 at 04:45:44PM -0400, Eli Barzilay wrote:

> 1. False belief: After you edit and `git add' a file, you will need to
>    commit it to make the change part of your history.
> 
>    Obvious counter example: edit a file and `git add' it; undo the
>    edit in the file and `git add' again -- you now have nothing to
>    commit.
> 
>    A way that I think will solve this: make `git add' notify you that
>    the changes that you just added canceled earlier changes and you're
>    back to a clean state.

I don't understand how this is a false belief. You _haven't_ made
anything a part of your history. It was already there, and you've done
nothing to the history.

But I thought your original question started out with a conflicted
merge:

>   mkdir /tmp/r1; cd /tmp/r1; git init
>   echo foo > file; git add file; git commit -m first
>   cd /tmp; git clone r1 r2
>   cd /tmp/r1; echo abc > file; git commit -m abc file
>   cd /tmp/r2; echo xyz > file; git commit -m xyz file
>   git fetch
>   git merge origin
>   echo xyz > file
>   git add file
>   git status -s

In that case you _do_ have to commit, or your history will not contain
the merge! Even though you happened to reject the other sides changes,
you still want to generate a merge commit showing that in your history
you have examined and rejected the other side's changes.

The only failing here, if any, is that "git status" does not say "you
are in the middle of a merge, and should commit it".

> 2. False belief: If you have a completely clear working directory and
>    index, then there's nothing for you to commit.  (At least without
>    forcing an empty commit.)
> 
>    Counter example: run this (simplified example)
> 
>      rm -rf /tmp/test; mkdir /tmp/test; cd /tmp/test; git init
>      echo foo > file; git add file; git commit -m first
>      git branch a-branch;   echo abc > file; git commit -m abc file
>      git checkout a-branch; echo xyz > file; git commit -m xyz file
>      git merge master; echo xyz > file; git add file
>      git status
> 
>    That last `status' will happily tell you that "nothing to commit
>    (working directory clean)" -- but `git commit' *will* commit the
>    merge.

Yeah, probably it should detect the presence of .git/MERGE_HEAD and
print a different message.

> 3. False belief: if your working directory and your index are dirty,
>    then there *is* something for you to commit.
> 
>    Obvious counter example: edit a file and `git add' it; undo the
>    edit in the file but *don't* `git add' again -- `git status -s'
>    will now say:
> 
>      MM file
> 
>    And now:
> 
>      $ git commit .
>      # On branch master
>      nothing to commit (working directory clean)
> 
>    but the status is still not cleared.  Trying to checkout a
>    different branch gives me the barf.

I think you misunderstand how "git commit ." works. It already means
"git add . && git commit". So you are actually _removing_ the thing to
commit in the first step. Running "git commit" would work.

Which is what you suggest:

>    A way that I think will solve this: make `git commit <path>' add
>    the paths before committing -- and if `add' says something, it will
>    say that here and clarify what happened.  But this is probably too
>    much of a change, so alternatively `git commit' would notice that
>    there was nothing to commit because of this state, and `add' the
>    right files to clear out the status (after saying something about
>    it).

Except that I guess you want the add process to say "the thing you added
is the same as HEAD, so you just reverted the original thing you added".
Personally I would find such a notification annoying.

-Peff

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Re: Problem with git merge/rebase with conflicts
  2010-05-08  5:20     ` Jeff King
@ 2010-05-08  5:52       ` Eli Barzilay
  0 siblings, 0 replies; 5+ messages in thread
From: Eli Barzilay @ 2010-05-08  5:52 UTC (permalink / raw)
  To: Jeff King; +Cc: Junio C Hamano, git

On May  8, Jeff King wrote:
> On Thu, May 06, 2010 at 04:45:44PM -0400, Eli Barzilay wrote:
> 
> > 1. False belief: After you edit and `git add' a file, you will
> >    need to commit it to make the change part of your history.
> > 
> >    Obvious counter example: edit a file and `git add' it; undo the
> >    edit in the file and `git add' again -- you now have nothing to
> >    commit.
> > 
> >    A way that I think will solve this: make `git add' notify you
> >    that the changes that you just added canceled earlier changes
> >    and you're back to a clean state.
> 
> I don't understand how this is a false belief. You _haven't_ made
> anything a part of your history. It was already there, and you've
> done nothing to the history.

Well, the false belief here is following every text that (very
reasonably) tells you that you should `git add' the file and then `git
commit' it.  Obviously, with a cooked example like that things are
made very clear -- but what if I worked on something for a while
(adding stuff to the index as I go), and missed the fact that the file
is eventually at exactly where it started?  Even with this it's
probably not too bad as is, but with merges it gets even more
potential to be confusing.  In any case, I'm not saying that anything
is wrong -- just that it would be nice if `git add' told me about it,
so I can never see a transcript that ends with:

  $ git add foo
  $ git commit
  ... nothing to commit

since that canceling add will tell me explicitly that this addition
got things back to a state of having no changes.  (And I don't see any
harm in that -- if you want to explicitly revert things back you'd use
reset or something, so this change is something that you'd only see if
you were confused as above.)


> But I thought your original question started out with a conflicted
> merge:
> 
> >   mkdir /tmp/r1; cd /tmp/r1; git init
> >   echo foo > file; git add file; git commit -m first
> >   cd /tmp; git clone r1 r2
> >   cd /tmp/r1; echo abc > file; git commit -m abc file
> >   cd /tmp/r2; echo xyz > file; git commit -m xyz file
> >   git fetch
> >   git merge origin
> >   echo xyz > file
> >   git add file
> >   git status -s
> 
> In that case you _do_ have to commit, or your history will not
> contain the merge! Even though you happened to reject the other
> sides changes, you still want to generate a merge commit showing
> that in your history you have examined and rejected the other side's
> changes.
> 
> The only failing here, if any, is that "git status" does not say
> "you are in the middle of a merge, and should commit it".

Yes, that was exactly the conclusion of my following point.  Well,
even more than that -- if `git add' will tell you about getting into a
clean state, then you'd get this for the first case above:

  $ git add foo
  note: this addition canceled out all changes
  $ git commit
  ... nothing to commit         # <-- this is obvious now
  $ git status -s
                                # <-- as is the lack of output here

and for the merge case, `git add' could note that, in addition to a
clean state, you still have a merge to finish, so it could say this:

  $ git merge blah
  ...
  $ git add foo
  note: this addition canceled out all changes,
  but you still have a pending merge to commit
  $ git status -s
  (merge pending)               # <-- this is my item#2 suggestion


> > 3. False belief: if your working directory and your index are dirty,
> >    then there *is* something for you to commit.
> > 
> >    Obvious counter example: edit a file and `git add' it; undo the
> >    edit in the file but *don't* `git add' again -- `git status -s'
> >    will now say:
> > 
> >      MM file
> > 
> >    And now:
> > 
> >      $ git commit .
> >      # On branch master
> >      nothing to commit (working directory clean)
> > 
> >    but the status is still not cleared.  Trying to checkout a
> >    different branch gives me the barf.
> 
> I think you misunderstand how "git commit ." works. It already means
> "git add . && git commit". So you are actually _removing_ the thing to
> commit in the first step. Running "git commit" would work.
> 
> Which is what you suggest:
> 
> >    A way that I think will solve this: make `git commit <path>'
> >    add the paths before committing -- and if `add' says something,
> >    it will say that here and clarify what happened.  But this is
> >    probably too much of a change, so alternatively `git commit'
> >    would notice that there was nothing to commit because of this
> >    state, and `add' the right files to clear out the status (after
> >    saying something about it).
> 
> Except that I guess you want the add process to say "the thing you
> added is the same as HEAD, so you just reverted the original thing
> you added".

Yes.


> Personally I would find such a notification annoying.

Isn't this something that you'd never do intentionally?  I'm not
talking about doing this for any specific file in the commit (actually
the `add' part of the commit) -- I'm suggesting that it will say that
only if the result of adding stuff made the following commit do
nothing.  So this message would only annoy you if you've done some
changes and added them, then you edit the files back to the original
state, and then use `git add' or `git commit <paths>' (!) to add the
changes so you're back to a clean state.  This sounds like a very odd
way of undoing changes (especially with git that gives me about 200
ways to undo changes more directly...).

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-05-08  5:54 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-06 10:06 Problem with git merge/rebase with conflicts Eli Barzilay
2010-05-06 19:13 ` Junio C Hamano
2010-05-06 20:45   ` Eli Barzilay
2010-05-08  5:20     ` Jeff King
2010-05-08  5:52       ` Eli Barzilay

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).