threads / discuss / 2333

Now What?

Subject: Now What?

## tl;dr

20 messages between Nov 3, 2005 and Nov 6, 2005.

replies: 19people: 7as markdown or json

Jon Loeliger· Nov 3, 2005, 01:30 UTC · lore

The Other Day, I offered to help write up some parts of a "Something weird just happened. Now What?" document.

So, I'm now soliciting suggestions and/or tips that can be thrown together to form the basis of that document.

I have a few ideas and a rough outline up my sleeve, but I am curious to know what _you_ think needs to be covered.

I think one of the most crucial aspects that needs to be covered well is the "Merge Failed" problem. So, for starters, I'd like to get your suggestions on this particular issue. I know when I see the dreaded "merge by hand" message I often sit and stare, pondering "Now what?"

I feel that an explanation of all of the behind-the-scripts- in-.git communication files is needed. In particular these:

    FETCH_HEAD
    MERGE_HEAD
    LAST_MERGE
    MERGE_MSG

These need to be mentioned and explained because they frequently form exactly the critical missing link or starting point after a failed fetch or merge.

Finally, a procedure or style question. Should this write-up be in the form of a structured FAQ? A stand-alone expository document?

Thanks, jdl

Chris Shoemaker· Nov 3, 2005, 01:43 UTC · re: Jon Loeliger · lore

Re: Now What?

On Wed, Nov 02, 2005 at 07:30:37PM -0600, Jon Loeliger wrote:
Show 9 quoted lines
> 
> The Other Day, I offered to help write up some parts of
> a "Something weird just happened.  Now What?" document.
> 
> So, I'm now soliciting suggestions and/or tips that can
> be thrown together to form the basis of that document.
> 
> I have a few ideas and a rough outline up my sleeve, but
> I am curious to know what _you_ think needs to be covered.

"I cloned a remote repo. Then I pulled a branch from the remote repo and it started changing all the these files. I paniced and hit ctrl-c. Doh! I should have checked out the branch locally before pulling. Now what? How can I recover without cloning the repo again?"

In general, for each common operation, it'd be nice to explain how to "undo".

-chris
Junio C Hamano· Nov 3, 2005, 09:00 UTC · re: Chris Shoemaker · lore

Re: Now What?

Chris Shoemaker <c.shoemaker@cox.net> writes:
Show 5 quoted lines
> "I cloned a remote repo. Then I pulled a branch from the remote repo
> and it started changing all the these files.  I paniced and hit
> ctrl-c.  Doh!  I should have checked out the branch locally before
> pulling.  Now what?  How can I recover without cloning the repo
> again?"
Although I am not sure what this example is about,...
> In general, for each common operation, it'd be nice to explain how to
> "undo". 
I think this makes sense.
Jon Loeliger· Nov 3, 2005, 18:51 UTC · re: Chris Shoemaker · lore

Re: Now What?

On Wed, 2005-11-02 at 19:43, Chris Shoemaker wrote:
> In general, for each common operation, it'd be nice to explain how to
> "undo". 

So, I've take a stab at the "Reverse a Commit" process. I _think_ this just about covers all the usual cases and encompasses much of the lore already sent to the list.

I've punted (so far) on the details of the case where you want to reverse a buried or copied commit. I've read the howto/revert-branch-rebase.txt from Junio, but I'm not satisfied with it. While his write up there is very expository and comprehensive, I think it is overkill for a "simple recipe paragraph". Also, I was annoyed that "git revert -n commit-name" created conflicts and the reversal and merges didn't happen for me cleanly even though they did for Junio. I suck. So either I don't get it, or it isn't working quite right these days. Not sure. Advice sought.

Here's the gunk I have so far. Does this need to be simplified? Style OK? Send us more of same! God help us all, more ASCII art!?

You know, jdl

Reversing Commits ----------------- While a goal of a revision control system is to record changes and log them via commits, it is sometimes necessary to reverse a bogus or unwanted commit.

Making a commit in git is a reversible operation. In order to realize the reversal, either the index needs to be reverted to its prior state, or the contents of the files needs to be reverted and the index updated appropriately.

Here is a rough flow chart to help you. Discussion of the individual cases, along with example commands, follows.

+----------------------+
| Oops!  I didn't mean |
| to make that commit! |
+----------------------+
            |
            |
            |
            V
            ^
          /   \
        / Does  \
      /  anyone   \       "Live with it"
     < else have a > -----------------+
      \  copy of  /  Yes              |
        \ commit/                     |
          \ ? /                       |
            V                         |
            | No                      |
            |                         |
            |                         |
            V                         |
            ^                         |
          /   \                       |
        /  Is   \                     V
      /  commit   \  No            +--------------------+
     <  at top of  > ------------> | Generate and apply |
      \    HEAD   /     Ponder     | a reverse patch or |
        \   ?   /    Using StGit   | use git-revert     |
          \   /                    +--------------------+
            V
            | Yes
            |
            |
            V
            ^
          /   \
        /  Are  \
      /   there   \  No            +------------------------+
     <  local dir  > ------------> | # Blow it all away     | 
      \    mods   /                | git reset --hard HEAD^ | 
        \   ?   /                  +------------------------+
          \   /                                |
            V                                  |
                                               |
            | Yes                              |
            |                                  |
            |                                  |
            V                                  |
+----------------------------+                 V
| # I want to recommit it    |     +----------------------+
| git reset --soft HEAD^     |     | # Maybe cleanup some |  
|                            | --> | git prune            |
| # edit/fixup files by hand |     +----------------------+
| # maybe git-add new files  |
|                            |
| git commit -a -c ORIG_HEAD |
+----------------------------+

First, answer this question: Is it possible that someone else has a copy of this repository with the faulty commit? If so, or if the bogus commit is not the most recent commit on the head, it is very likely the correct course of action is to simply make a new commit that reverses the prior, bogus commit.

If there is no other copy of the repository with the bad commit, then fairly simple steps can be taken to reverse or remove the bogus commit, but it depends on the state of your working directory and your intent.

Reverse a buried or copied commit ---------------------------------

FIXME: While the "git diff | apply" works cleanly,
       the "git revert" didn't.  Ponder.
    Use git show-branch to determine the patch name you
    would like to revert.
        # "c" is some commit name, c^ its parent
	% git diff c c^ | git apply
	% git commit -m "Reverting commit...."
    Versus:
	% git revert -n c
[FIXME: Reference howto/revert-branch-rebase.txt]

If you find yourself doing this sort of apply-then-revert operation frequently, you might want to consider the StGit tool [FIXME: Reference StGit].

I didn't mean to do that commit! (And I want to blow it away!) ------------------------------------------------------------- If no other repository or copy of the bogus commit exists, you can easily remove the immediately prior commit on a head by simply reverting the index to its prior state.

First, make sure that your working tree matches the latest commit you are about to undo:

	# Should be no diffs here
	% git diff HEAD
	# Should be the bogus commit, forward:
	% git diff HEAD^
	# Should be the bogus commit, reverse:
	% git diff HEAD HEAD^
If that all looks fine, revert the index:
	# Revert the index to its prior (pre-commit) state
	% git reset --hard HEAD^

Be sure you have no other modified files in your working directory as they will be overwritten by this command. Entirely new files that are not mentioned in the index will be left untouched. However, files that are tracked in the index will be reverted to their HEAD^ state.

I didn't mean to do that commit! (And I want to recommit it.) -------------------------------------------------------------

After making a commit and finding a mistake either in the checked-in files or commit log message), you can fix it up by doing this:

	# Revert the index to its prior (pre-commit) state
	% git reset --soft HEAD^
	# Fix the checked-in files using your favorite editor
	# Maybe do git-add file(s) that was forgotten, etc.
        % git commit -a -c ORIG_HEAD

The --soft reset leaves the working tree files intact and just rewinds the .git/HEAD to whatever commit you specify. Here, the immediately prior index state, HEAD^. As a side effect it stores the original .git/HEAD in .git/ORIG_HEAD.

The -a flag to git-commit asks for all paths in the index to be updated. The lowercase -c flag to git-commit requests an opportunity to re-edit the prior commit log message.

Cleaning Up After A Reverted Commit ----------------------------------- If you have reverted a commit using either "git reset --hard" or "git reset --soft", you will very likely have created at least one dangling commit and possibly some dangling blobs as well. If you are certain you no longer need these objects, you can check for fuzz and prune them:

	# Fuzz check
	% git fsck-objects
	# Maybe inspect the danglers using git-cat-file
	# Remove the danglers, they aren't needed
	$ git prune
Junio C Hamano· Nov 6, 2005, 20:33 UTC · re: Jon Loeliger · lore

Re: Now What?

Jon Loeliger <jdl@freescale.com> writes:
Show 9 quoted lines
> On Wed, 2005-11-02 at 19:43, Chris Shoemaker wrote:
>
> ....  Also,
> I was annoyed that "git revert -n commit-name" created
> conflicts and the reversal and merges didn't happen
> for me cleanly even though they did for Junio.
>
> So either I don't get it, or it isn't working quite
> right these days.  Not sure.  Advice sought.

It's been a while since I used git-revert the last time. I should find time to run the examples myself.

> Reversing Commits
> -----------------
> While a goal of a revision control system is to record
> ...
The flow-chart based recipe is wonderful.
Peter Eriksen· Nov 3, 2005, 08:38 UTC · re: Jon Loeliger · lore

Re: Now What?

On Wed, Nov 02, 2005 at 07:30:37PM -0600, Jon Loeliger wrote: ...

Show 5 quoted lines
> I think one of the most crucial aspects that needs to be
> covered well is the "Merge Failed" problem.  So, for starters,
> I'd like to get your suggestions on this particular issue.
> I know when I see the dreaded "merge by hand" message I
> often sit and stare, pondering "Now what?"
Here's one I've done too many times:
~/git/git-core]cat .git/remotes/origin
URL: git://git.kernel.org/pub/scm/git/git.git
Pull: master:origin
~/git/git-core]git-checkout maint
~/git/git-core]git pull
Unpacking 222 objects
 100% (222/222) done
* committish: 9534f40bc42dd826cc26c8c8c84f6a8a5fc569f6
  branch 'master' of git://git.kernel.org/pub/scm/git/git
* refs/heads/origin: storing branch 'master' of
* git://git.kernel.org/pub/scm/git/git
Trying really trivial in-index merge...
fatal: Merge requires file-level merging
Nope.
Trying simple merge.
Simple merge failed, trying Automatic merge.
Auto-merging Documentation/tutorial.txt.
Auto-merging Makefile.
merge: warning: conflicts during merge
ERROR: Merge conflict in Makefile.
Auto-merging apply.c.
Auto-merging cache.h.
merge: warning: conflicts during merge
ERROR: Merge conflict in cache.h.
Auto-merging clone-pack.c.
Auto-merging connect.c.
merge: warning: conflicts during merge
ERROR: Merge conflict in connect.c.
Auto-merging daemon.c.
merge: warning: conflicts during merge
ERROR: Merge conflict in daemon.c.
Auto-merging debian/changelog.
merge: warning: conflicts during merge
ERROR: Merge conflict in debian/changelog.
Auto-merging fetch-pack.c.
merge: warning: conflicts during merge
ERROR: Merge conflict in fetch-pack.c.
Auto-merging git-branch.sh.
Auto-merging git-checkout.sh.
Auto-merging git-clone.sh.
Auto-merging git-cvsimport.perl.
merge: warning: conflicts during merge
ERROR: Merge conflict in git-cvsimport.perl.
Auto-merging git-fetch.sh.
Auto-merging git-parse-remote.sh.
Auto-merging git-tag.sh.
Auto-merging quote.c.
merge: warning: conflicts during merge
ERROR: Merge conflict in quote.c.
Auto-merging quote.h.
merge: warning: conflicts during merge
ERROR: Merge conflict in quote.h.
Auto-merging refs.c.
Auto-merging rev-list.c.
Auto-merging send-pack.c.
Auto-merging sha1_name.c.
merge: warning: conflicts during merge
ERROR: Merge conflict in sha1_name.c.
Auto-merging upload-pack.c.
merge: warning: conflicts during merge
ERROR: Merge conflict in upload-pack.c.
fatal: merge program failed
Automatic merge failed; fix up by hand
Indeed, what now?
Regards,
Peter
Junio C Hamano· Nov 3, 2005, 10:00 UTC · re: Peter Eriksen · lore

Re: Now What?

"Peter Eriksen" <s022018@student.dtu.dk> writes:
Show 8 quoted lines
> Here's one I've done too many times:
>
> ~/git/git-core]cat .git/remotes/origin
> URL: git://git.kernel.org/pub/scm/git/git.git
> Pull: master:origin
>
> ~/git/git-core]git-checkout maint
> ~/git/git-core]git pull

You are merging my master into your "maint", probably a copy of my (previous) maint.

What now? Depends on what you wanted to do. If what you wanted to do was to merge my "master" to your "maint", then you would resolve the conflicts by hand, but probably that was not what you wanted to do.

After that pull, your repository is in this state:
. the index file and working tree is somewhere between your
  "maint" and my "master".  "somewhere between" is because the
  merge obviously failed.
. the "maint" head has not moved.  Your .git/HEAD points at the
  "maint" branch.
. the "origin" head points at my latest "master" head.

If you keep a copy of my "master" plus zero or more of your own development in your "master" branch, and what you wanted to do was to build my "master" plus those developments of your own, then:

	$ git checkout -f master
        $ git pull . origin

If your "master" is just a vanilla copy of my "master", then this pull would result in a fast forward, and "master" and "origin" will point at the same commit after this pull operation. Otherwise, you would merge your changes and my "master" updates into your "master" branch.

If what you wanted to do was to build my "master" vanilla, then:
	$ git checkout -f origin

because your remotes/origin says "origin" is meant to be a straight copy of my "master".

A good habit to get into is, before pulling, make sure:
. your index matches your HEAD.
. the local modification (i.e. what git-diff-files would report)
  is something you do not mind losing.
. you are on the right branch you want to pull into (check with
  "git branch").
Daniel Barkalow· Nov 3, 2005, 17:05 UTC · re: Junio C Hamano · lore

Re: Now What?

On Thu, 3 Nov 2005, Junio C Hamano wrote:
Show 13 quoted lines
> "Peter Eriksen" <s022018@student.dtu.dk> writes:
> 
> > Here's one I've done too many times:
> >
> > ~/git/git-core]cat .git/remotes/origin
> > URL: git://git.kernel.org/pub/scm/git/git.git
> > Pull: master:origin
> >
> > ~/git/git-core]git-checkout maint
> > ~/git/git-core]git pull
> 
> You are merging my master into your "maint", probably a copy of
> my (previous) maint.

I think the situation is that he really wanted to update master, but forgot that he was on the maint branch. So now he's in a merge of things he didn't actually want to merge and wants to get back to not having junk all over the place (some files that need to be merged, some files that have been merged, new files, removed files, etc).

	-Daniel
*This .sig left intentionally blank*
Linus Torvalds· Nov 3, 2005, 17:27 UTC · re: Daniel Barkalow · lore

Re: Now What?

On Thu, 3 Nov 2005, Daniel Barkalow wrote:
Show 6 quoted lines
> 
> I think the situation is that he really wanted to update master, but 
> forgot that he was on the maint branch. So now he's in a merge of things 
> he didn't actually want to merge and wants to get back to not having junk 
> all over the place (some files that need to be merged, some files that 
> have been merged, new files, removed files, etc).

And that's exactly what "git reset --hard" is there for. It will reset to the old head of the branch you are on (ie HEAD), and get rid of everything that was done to the tree.

		Linus
Junio C Hamano· Nov 3, 2005, 18:38 UTC · re: Linus Torvalds · lore

Re: Now What?

Linus Torvalds <torvalds@osdl.org> writes:
> And that's exactly what "git reset --hard" is there for. It will reset to 
> the old head of the branch you are on (ie HEAD), and get rid of everything 
> that was done to the tree.

OK, then let's rewrite the procedure using 'reset --hard'. Then we do not have to use 'checkout -f' afterwards. The advantage of this approach is that 'reset --hard' would remove the new files the failed merge might have left in your working tree, while using 'checkout -f' would.

What now? Depends on what you wanted to do. If what you wanted to do was to merge my "master" to your "maint", then you would resolve the conflicts by hand, but probably that was not what you wanted to do.

After that pull, your repository is in this state:
. the index file and working tree is somewhere between your
  "maint" and my "master".  "somewhere between" is because the
  merge obviously failed.
. the "maint" head has not moved.  Your .git/HEAD points at the
  "maint" branch.
. the "origin" head points at my latest "master" head.

First thing is to bring your tree to a known state, to make recovery easier.

	$ git reset --hard

would match your working tree to your .git/HEAD, i.e. your "maint".

If you keep a copy of my "master" plus zero or more of your own development in your "master" branch, and what you wanted to do was to build my "master" plus those developments of your own, then:

	$ git checkout master
        $ git pull . origin

If your "master" is just a vanilla copy of my "master", then this pull would result in a fast forward, and "master" and "origin" will point at the same commit after this pull operation. Otherwise, you would merge your changes and my "master" updates into your "master" branch.

If what you wanted to do was to build my "master" vanilla, then:
	$ git checkout origin

because your remotes/origin says "origin" is meant to be a straight copy of my "master".

A good habit to get into is, before pulling, make sure:
. your index matches your HEAD.
. the local modification (i.e. what git-diff-files would report)
  is something you do not mind losing.
. you are on the right branch you want to pull into (check with
  "git branch").
Peter Eriksen· Nov 3, 2005, 17:30 UTC · re: Daniel Barkalow · lore

Re: Now What?

On Thu, Nov 03, 2005 at 12:05:42PM -0500, Daniel Barkalow wrote:
Show 21 quoted lines
> On Thu, 3 Nov 2005, Junio C Hamano wrote:
> 
> > "Peter Eriksen" <s022018@student.dtu.dk> writes:
> > 
> > > Here's one I've done too many times:
> > >
> > > ~/git/git-core]cat .git/remotes/origin
> > > URL: git://git.kernel.org/pub/scm/git/git.git
> > > Pull: master:origin
> > >
> > > ~/git/git-core]git-checkout maint
> > > ~/git/git-core]git pull
> > 
> > You are merging my master into your "maint", probably a copy of
> > my (previous) maint.
> 
> I think the situation is that he really wanted to update master, but 
> forgot that he was on the maint branch. So now he's in a merge of things 
> he didn't actually want to merge and wants to get back to not having junk 
> all over the place (some files that need to be merged, some files that 
> have been merged, new files, removed files, etc).

I really should have stated that from the beginning. Yes, I forgot, I had checked out some other branch and thought (the first I times assumed) that it would merge into master. So it's really just an accident, which I would think, is not that uncommon for newcommers.

Peter
Junio C Hamano· Nov 3, 2005, 22:07 UTC · re: Daniel Barkalow · lore

Re: Now What?

Daniel Barkalow <barkalow@iabervon.org> writes:
Show 16 quoted lines
> On Thu, 3 Nov 2005, Junio C Hamano wrote:
>
>> "Peter Eriksen" <s022018@student.dtu.dk> writes:
>> 
>> > ~/git/git-core]cat .git/remotes/origin
>> > URL: git://git.kernel.org/pub/scm/git/git.git
>> > Pull: master:origin
>> >
>> > ~/git/git-core]git-checkout maint
>> > ~/git/git-core]git pull
>> 
>> You are merging my master into your "maint", probably a copy of
>> my (previous) maint.
>
> I think the situation is that he really wanted to update master, but 
> forgot that he was on the maint branch.

I wonder if it would make sense to have something in .git/remotes/ file that says "run merge only when I am on frotz branch", like this:

        ~/git/git-core]cat .git/remotes/origin
        URL: git://git.kernel.org/pub/scm/git/git.git
        Pull: master:origin
	Fetch-Only-Unless: master
        ~/git/git-core]git-checkout maint
	~/git/git-core]git pull
	warning: not merging because you are not on 'master' branch.

This would make the above "git pull" behave identical to "git fetch", and the user can then do:

	$ git checkout master
        $ git pull . origin
Useful?  Useless?
Josef Weidendorfer· Nov 3, 2005, 22:33 UTC · re: Junio C Hamano · lore

Re: Now What?

On Thursday 03 November 2005 23:07, Junio C Hamano wrote:
Show 12 quoted lines
> I wonder if it would make sense to have something in .git/remotes/
> file that says "run merge only when I am on frotz branch", like
> this:
> 
>         ~/git/git-core]cat .git/remotes/origin
>         URL: git://git.kernel.org/pub/scm/git/git.git
>         Pull: master:origin
> 	Fetch-Only-Unless: master
> 
>         ~/git/git-core]git-checkout maint
> 	~/git/git-core]git pull
> 	warning: not merging because you are not on 'master' branch.

This is quite limiting, if you keep multiple branches from origin in your repository. It would be better to be able to specify per-branch Pull lines. I.e. the default pull action depends on the branch you are on.

        URL: git://git.kernel.org/pub/scm/git/git.git
        Pull(master): master:origin
        ~/git/git-core]git-checkout maint
 	~/git/git-core]git pull
 	warning: no default pull action for branch 'maint' specified
Syntax arguable.
Josef
Daniel Barkalow· Nov 4, 2005, 17:06 UTC · re: Junio C Hamano · lore

Re: Now What?

On Thu, 3 Nov 2005, Junio C Hamano wrote:
Show 39 quoted lines
> Daniel Barkalow <barkalow@iabervon.org> writes:
> 
> > On Thu, 3 Nov 2005, Junio C Hamano wrote:
> >
> >> "Peter Eriksen" <s022018@student.dtu.dk> writes:
> >> 
> >> > ~/git/git-core]cat .git/remotes/origin
> >> > URL: git://git.kernel.org/pub/scm/git/git.git
> >> > Pull: master:origin
> >> >
> >> > ~/git/git-core]git-checkout maint
> >> > ~/git/git-core]git pull
> >> 
> >> You are merging my master into your "maint", probably a copy of
> >> my (previous) maint.
> >
> > I think the situation is that he really wanted to update master, but 
> > forgot that he was on the maint branch.
> 
> I wonder if it would make sense to have something in .git/remotes/
> file that says "run merge only when I am on frotz branch", like
> this:
> 
>         ~/git/git-core]cat .git/remotes/origin
>         URL: git://git.kernel.org/pub/scm/git/git.git
>         Pull: master:origin
> 	Fetch-Only-Unless: master
> 
>         ~/git/git-core]git-checkout maint
> 	~/git/git-core]git pull
> 	warning: not merging because you are not on 'master' branch.
> 
> This would make the above "git pull" behave identical to "git
> fetch", and the user can then do:
> 
> 	$ git checkout master
>         $ git pull . origin
> 
> Useful?  Useless?

People probably want to merge master into their personal work branches, though; I think it would be better to have it list branches into which it shouldn't be merged. I think the pair of "maint" and "master" are special, in that they get different fixes for the same problems, and so they'll merge badly or to a wrong result.

	-Daniel
*This .sig left intentionally blank*
Linus Torvalds· Nov 3, 2005, 17:25 UTC · re: Peter Eriksen · lore

Re: Now What?

On Thu, 3 Nov 2005, Peter Eriksen wrote:
Show 69 quoted lines
> 
> Here's one I've done too many times:
> 
> ~/git/git-core]cat .git/remotes/origin
> URL: git://git.kernel.org/pub/scm/git/git.git
> Pull: master:origin
> 
> ~/git/git-core]git-checkout maint
> ~/git/git-core]git pull
> Unpacking 222 objects
>  100% (222/222) done
> * committish: 9534f40bc42dd826cc26c8c8c84f6a8a5fc569f6
>   branch 'master' of git://git.kernel.org/pub/scm/git/git
> * refs/heads/origin: storing branch 'master' of
> * git://git.kernel.org/pub/scm/git/git
> Trying really trivial in-index merge...
> fatal: Merge requires file-level merging
> Nope.
> Trying simple merge.
> Simple merge failed, trying Automatic merge.
> Auto-merging Documentation/tutorial.txt.
> Auto-merging Makefile.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in Makefile.
> Auto-merging apply.c.
> Auto-merging cache.h.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in cache.h.
> Auto-merging clone-pack.c.
> Auto-merging connect.c.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in connect.c.
> Auto-merging daemon.c.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in daemon.c.
> Auto-merging debian/changelog.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in debian/changelog.
> Auto-merging fetch-pack.c.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in fetch-pack.c.
> Auto-merging git-branch.sh.
> Auto-merging git-checkout.sh.
> Auto-merging git-clone.sh.
> Auto-merging git-cvsimport.perl.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in git-cvsimport.perl.
> Auto-merging git-fetch.sh.
> Auto-merging git-parse-remote.sh.
> Auto-merging git-tag.sh.
> Auto-merging quote.c.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in quote.c.
> Auto-merging quote.h.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in quote.h.
> Auto-merging refs.c.
> Auto-merging rev-list.c.
> Auto-merging send-pack.c.
> Auto-merging sha1_name.c.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in sha1_name.c.
> Auto-merging upload-pack.c.
> merge: warning: conflicts during merge
> ERROR: Merge conflict in upload-pack.c.
> fatal: merge program failed
> Automatic merge failed; fix up by hand
> 
> Indeed, what now?
You can do two things:
 a) decide not to merge at all:
	git reset --hard
    and you're done. This is what you want to do when you just pulled the 
    wrong branch, for example.

IF you pulled the right branch, and you knew you had other changes through other pulls or because you just had done your own development, you want to look at:

 b) Try to resolve the merge. Do a "git diff" and look what was unresolved 
    (by looking for those bog-standard resolve conflict markers like 
    "<<<<< old ===== new >>>>>".
    Edit the conflicts by hand to what you want them to be, and do
	git commit --all
    to commit your manual merge.

Note that if you start doing (b) and you decide it's too much for you, you can always go back to (a) in the end and ask for help from the people involved.

			Linus
Junio C Hamano· Nov 3, 2005, 08:58 UTC · re: Jon Loeliger · lore

Re: Now What?

Jon Loeliger <jdl@freescale.com> writes:
Show 11 quoted lines
> I feel that an explanation of all of the behind-the-scripts-
> in-.git communication files is needed.  In particular these:
>
>     FETCH_HEAD
>     MERGE_HEAD
>     LAST_MERGE
>     MERGE_MSG
>
> These need to be mentioned and explained because they
> frequently form exactly the critical missing link or
> starting point after a failed fetch or merge.

I am not so sure if it would help to know details of the above four files to answer "Now What" question, but I'll try to describe them near the end of this message.

Before that, here is a cookbook failed pull/merge resolution procedure.

	$ git pull some-where
	Gaah ... resolve by hand.
Oops, it failed.  Now what?

First, if your index did not match your HEAD before pulling/merging, the merge strategies will refuse to merge in the changes and would fail without touching your working tree (so you would not even see "resolve by hand" message). If you want to proceed, you need to somehow match your HEAD and your index to retry. There are two possibilities.

(1) if you were deep in a middle of something, snapshot your
    changes and rewind the current tree.
	$ git commit -a -m 'WIP'
	$ git branch save-wip
        $ git reset --hard HEAD^
    and then retry merge or pull.  Later you would want to
    resurrect what you did from save-wip branch (e.g. "git diff
    save-wip^ save-wip | git apply" after finishing your
    merge).
(2) if you did not have much worth saving, just rewind the
    changes.  Optionally you could save the diff just in case.
	$ git diff HEAD >tmp-wip.diff
        $ git reset --hard
    and then retry merge or pull.

Now that case is out of our way, I'll discuss the case where your index did match your HEAD from here on. You pulled from remote, merge strategy tried to do its work, and did not find a clean automerge.

At this point, the automerge procedure would have already updated your index for paths that cleanly merged. The rest are left in your working tree, so this diff would show what remains to be resolved:

        $ git diff

You would most likely see some <<<< ==== >>>> conflict markers. Resolving them by hand is hopefully something familiar to CVS or SVN migrants, so "Now what" document may not have to talk about what these conflict markers mean ("between <<<< and ==== are your version, between ==== and >>>> are their version", or something like that --- I may be getting this particular detail wrong in this sentence, so you should check).

After resolving them by hand, you would want to see what got changed from _your_ version for sanity checking, because you are hopefully more familiar with your version than theirs, and reading diff between theirs might be more difficult. So check

	$ git diff HEAD

to see what changes this pull brought in, including the conflict resolution you just did. On the other hand,

	$ git diff MERGE_HEAD

would show diff from their head, so you would see what you did to their tree.

After checking the diffs, if things look OK, compiling and testing is the same procedure as you would normally do before making any commit. Then

	$ git commit -a

(as usual, you can drop '-a' if you manually 'git-update-index' all the necessary paths before this step) would give you the regular commit message editor, with a reminder "you are committing a merge", with prepared message "merge from some-where repository". Edit it and exit the editor normally to make the merge commit, and you are done.

Now to the communication files.
>     FETCH_HEAD

This file lists refs the git-fetch command (run from git-pull) retrieved from the remote. Usually it marks everything but one as 'not-for-merge'. The one that is not marked as 'not-for-merge' is the commit you are merging into the current head. This is not looked at by the merge machinery, but git-pull uses it to decide which commits to pass to git-merge.

>     MERGE_HEAD

This is present only after a failed automerge, by git-merge, and lists the commits that you are merging into the current head (typically only one) -- the same as the ones not marked as 'not-for-merge' in FETCH_HEAD, because this file records the commits given to git-merge.

>     LAST_MERGE

This is more or less historical curiosity and only git-resolve uses it. Records almost the same information as MERGE_HEAD.

>     MERGE_MSG

This is created by git-pull from FETCH_HEAD to format a human readable autocommit log.

> Finally, a procedure or style question.  Should this
> write-up be in the form of a structured FAQ?  A stand-alone
> expository document?

One useful thing would be to have a cut&paste ready example that would cover constructing two branches/repos, pulling a branch from one to the other and causing an actual conflict, and show how to resolve it and make a commit, in a section in Tutorial. I think we already have something like that there.

Another good thing would be, after proofreading this message and making necessary corrections, send it as a patch form to add it as a new file under Documentation/howto/.

Junio C Hamano· Nov 3, 2005, 20:55 UTC · re: Jon Loeliger · lore

Re: Now What?

Jon Loeliger <jdl@freescale.com> writes:
> Finally, a procedure or style question.  Should this
> write-up be in the form of a structured FAQ?  A stand-alone
> expository document?

Earlier I suggested bunch of unconnected Documentation/howto pages, but I'd like to take it back at least partially. I have two alternatives; I do not know which one I prefer more...

A table-of-contents (FAQ-list) with task-oriented categorization would help guide the users facing "Now What?" situation. It might start like this:

	It broke after you tried to ...
	* pull from remote
	  breakage #1 --> see this...
	  breakage #2 --> see that...
	  ...
        * checkout a branch
	  breakage #1 --> see this...
	  breakage #2 --> see that...
	  ...
and each breakage and solution would be a separate document.

If we go with this separate FAQ-list approach, I'd love to keep the result under Documentation/ hierarchy we ship as part of the source, but I suspect that building-up this kind of thing might be better suited to Wiki. I wonder if there is a Wiki whose document storage format is in asciidoc, and uses git as its revision control backend. Then we could let people update Wiki, and occasionally merge from there. We also should be able to push things back to Wiki, essentially treating Wiki as one of the repositories from the git side. Hmm...

The other alternative is to add "NOW WHAT" section to each man page. The idea is that "if the last command you ran was this command and if it did not do what you wanted it to do, here are its common failure modes and how you would recover from them". So the materials we covered during the failed pull/merge discussion would go to "NOW WHAT" section of git-pull(1), with perhaps git-merge(1) saying "See also".

We would want "EXAMPLES" section for all the major commands as suggested by Linus anyway, and going this way we _may_ be able to get away without coming up with the higher level problem categorization; the user would at least know what the last command he tried to use was already.

Josef Weidendorfer· Nov 3, 2005, 22:17 UTC · re: Junio C Hamano · lore

Re: Now What?

On Thursday 03 November 2005 21:55, Junio C Hamano wrote:
> be better suited to Wiki.  I wonder if there is a Wiki whose
> document storage format is in asciidoc, and uses git as its
> revision control backend.

I wonder if Git is the best SCM for a Wiki, as you want per-file revisions in a Wiki: when reverting a page to a previous version, this should not modify other pages. So you have an index and a HEAD for every file. To snapshot a state of such a multihead repository, it would be nice to have tag objects able to hold multiple SHAs of commits. Or can we use tree objects for this?

Josef
Junio C Hamano· Nov 3, 2005, 22:51 UTC · re: Josef Weidendorfer · lore

Re: Now What?

Josef Weidendorfer <Josef.Weidendorfer@gmx.de> writes:
Show 8 quoted lines
> On Thursday 03 November 2005 21:55, Junio C Hamano wrote:
>> be better suited to Wiki.  I wonder if there is a Wiki whose
>> document storage format is in asciidoc, and uses git as its
>> revision control backend.
>
> I wonder if Git is the best SCM for a Wiki, as you want per-file
> revisions in a Wiki: when reverting a page to a previous version,
> this should not modify other pages.

Sorry, I do not see why per-file revisioning is mandatory. Wouldn't revert or edit of a single page be just a new commit of the new whole tree with just a single path changed?

I understand that whole tree history may not be much useful in Wiki environment, but I do not see why it would hurt to have a whole tree history (except perhaps the commit log may not be very useful).

In fact, wouldn't svnwiki already does the same thing?
Josef Weidendorfer· Nov 3, 2005, 23:26 UTC · re: Junio C Hamano · lore

Re: Now What?

On Thursday 03 November 2005 23:51, Junio C Hamano wrote:
Show 7 quoted lines
> > I wonder if Git is the best SCM for a Wiki, as you want per-file
> > revisions in a Wiki: when reverting a page to a previous version,
> > this should not modify other pages.
> 
> Sorry, I do not see why per-file revisioning is mandatory.
> Wouldn't revert or edit of a single page be just a new commit of
> the new whole tree with just a single path changed?

You are right. Obviously I should get some sleep ;-)

As you said, by adding a new commit for every page revert, you get a really messy history. If there is vandalism in a Wiki, wouldn't it be better to be able to get rid of spam versions of one Wiki page?

> In fact, wouldn't svnwiki already does the same thing?
Probably. I don't know it.
Josef

← back to recent threads