* Now What?
@ 2005-11-03 1:30 Jon Loeliger
2005-11-03 1:43 ` Chris Shoemaker
` (3 more replies)
0 siblings, 4 replies; 20+ messages in thread
From: Jon Loeliger @ 2005-11-03 1:30 UTC (permalink / raw)
To: git
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
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 1:30 Now What? Jon Loeliger
@ 2005-11-03 1:43 ` Chris Shoemaker
2005-11-03 9:00 ` Junio C Hamano
2005-11-03 18:51 ` Jon Loeliger
2005-11-03 8:38 ` Peter Eriksen
` (2 subsequent siblings)
3 siblings, 2 replies; 20+ messages in thread
From: Chris Shoemaker @ 2005-11-03 1:43 UTC (permalink / raw)
To: Jon Loeliger; +Cc: git
On Wed, Nov 02, 2005 at 07:30:37PM -0600, Jon Loeliger wrote:
>
> 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
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 1:30 Now What? Jon Loeliger
2005-11-03 1:43 ` Chris Shoemaker
@ 2005-11-03 8:38 ` Peter Eriksen
2005-11-03 10:00 ` Junio C Hamano
2005-11-03 17:25 ` Linus Torvalds
2005-11-03 8:58 ` Junio C Hamano
2005-11-03 20:55 ` Junio C Hamano
3 siblings, 2 replies; 20+ messages in thread
From: Peter Eriksen @ 2005-11-03 8:38 UTC (permalink / raw)
To: Jon Loeliger; +Cc: git
On Wed, Nov 02, 2005 at 07:30:37PM -0600, Jon Loeliger wrote:
...
> 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
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 1:30 Now What? Jon Loeliger
2005-11-03 1:43 ` Chris Shoemaker
2005-11-03 8:38 ` Peter Eriksen
@ 2005-11-03 8:58 ` Junio C Hamano
2005-11-03 20:55 ` Junio C Hamano
3 siblings, 0 replies; 20+ messages in thread
From: Junio C Hamano @ 2005-11-03 8:58 UTC (permalink / raw)
To: Jon Loeliger; +Cc: git
Jon Loeliger <jdl@freescale.com> writes:
> 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/.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 1:43 ` Chris Shoemaker
@ 2005-11-03 9:00 ` Junio C Hamano
2005-11-03 18:51 ` Jon Loeliger
1 sibling, 0 replies; 20+ messages in thread
From: Junio C Hamano @ 2005-11-03 9:00 UTC (permalink / raw)
To: Chris Shoemaker; +Cc: git
Chris Shoemaker <c.shoemaker@cox.net> writes:
> "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.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 8:38 ` Peter Eriksen
@ 2005-11-03 10:00 ` Junio C Hamano
2005-11-03 17:05 ` Daniel Barkalow
2005-11-03 17:25 ` Linus Torvalds
1 sibling, 1 reply; 20+ messages in thread
From: Junio C Hamano @ 2005-11-03 10:00 UTC (permalink / raw)
To: Peter Eriksen; +Cc: git, Jon Loeliger
"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.
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").
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 10:00 ` Junio C Hamano
@ 2005-11-03 17:05 ` Daniel Barkalow
2005-11-03 17:27 ` Linus Torvalds
` (2 more replies)
0 siblings, 3 replies; 20+ messages in thread
From: Daniel Barkalow @ 2005-11-03 17:05 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Peter Eriksen, git, Jon Loeliger
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).
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 8:38 ` Peter Eriksen
2005-11-03 10:00 ` Junio C Hamano
@ 2005-11-03 17:25 ` Linus Torvalds
1 sibling, 0 replies; 20+ messages in thread
From: Linus Torvalds @ 2005-11-03 17:25 UTC (permalink / raw)
To: Peter Eriksen; +Cc: Jon Loeliger, git
On Thu, 3 Nov 2005, Peter Eriksen wrote:
>
> 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
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 17:05 ` Daniel Barkalow
@ 2005-11-03 17:27 ` Linus Torvalds
2005-11-03 18:38 ` Junio C Hamano
2005-11-03 17:30 ` Peter Eriksen
2005-11-03 22:07 ` Junio C Hamano
2 siblings, 1 reply; 20+ messages in thread
From: Linus Torvalds @ 2005-11-03 17:27 UTC (permalink / raw)
To: Daniel Barkalow; +Cc: Junio C Hamano, Peter Eriksen, git, Jon Loeliger
On Thu, 3 Nov 2005, Daniel Barkalow wrote:
>
> 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
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 17:05 ` Daniel Barkalow
2005-11-03 17:27 ` Linus Torvalds
@ 2005-11-03 17:30 ` Peter Eriksen
2005-11-03 22:07 ` Junio C Hamano
2 siblings, 0 replies; 20+ messages in thread
From: Peter Eriksen @ 2005-11-03 17:30 UTC (permalink / raw)
To: git
On Thu, Nov 03, 2005 at 12:05:42PM -0500, Daniel Barkalow wrote:
> 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
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 17:27 ` Linus Torvalds
@ 2005-11-03 18:38 ` Junio C Hamano
0 siblings, 0 replies; 20+ messages in thread
From: Junio C Hamano @ 2005-11-03 18:38 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Daniel Barkalow, Peter Eriksen, git, Jon Loeliger
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").
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 1:43 ` Chris Shoemaker
2005-11-03 9:00 ` Junio C Hamano
@ 2005-11-03 18:51 ` Jon Loeliger
2005-11-06 20:33 ` Junio C Hamano
1 sibling, 1 reply; 20+ messages in thread
From: Jon Loeliger @ 2005-11-03 18:51 UTC (permalink / raw)
To: Git List
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
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 1:30 Now What? Jon Loeliger
` (2 preceding siblings ...)
2005-11-03 8:58 ` Junio C Hamano
@ 2005-11-03 20:55 ` Junio C Hamano
2005-11-03 22:17 ` Josef Weidendorfer
3 siblings, 1 reply; 20+ messages in thread
From: Junio C Hamano @ 2005-11-03 20:55 UTC (permalink / raw)
To: Jon Loeliger; +Cc: git
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.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 17:05 ` Daniel Barkalow
2005-11-03 17:27 ` Linus Torvalds
2005-11-03 17:30 ` Peter Eriksen
@ 2005-11-03 22:07 ` Junio C Hamano
2005-11-03 22:33 ` Josef Weidendorfer
2005-11-04 17:06 ` Daniel Barkalow
2 siblings, 2 replies; 20+ messages in thread
From: Junio C Hamano @ 2005-11-03 22:07 UTC (permalink / raw)
To: Daniel Barkalow; +Cc: git
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?
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 20:55 ` Junio C Hamano
@ 2005-11-03 22:17 ` Josef Weidendorfer
2005-11-03 22:51 ` Junio C Hamano
0 siblings, 1 reply; 20+ messages in thread
From: Josef Weidendorfer @ 2005-11-03 22:17 UTC (permalink / raw)
To: git
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
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 22:07 ` Junio C Hamano
@ 2005-11-03 22:33 ` Josef Weidendorfer
2005-11-04 17:06 ` Daniel Barkalow
1 sibling, 0 replies; 20+ messages in thread
From: Josef Weidendorfer @ 2005-11-03 22:33 UTC (permalink / raw)
To: git
On Thursday 03 November 2005 23:07, Junio C Hamano wrote:
> 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
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 22:17 ` Josef Weidendorfer
@ 2005-11-03 22:51 ` Junio C Hamano
2005-11-03 23:26 ` Josef Weidendorfer
0 siblings, 1 reply; 20+ messages in thread
From: Junio C Hamano @ 2005-11-03 22:51 UTC (permalink / raw)
To: Josef Weidendorfer; +Cc: git
Josef Weidendorfer <Josef.Weidendorfer@gmx.de> writes:
> 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?
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 22:51 ` Junio C Hamano
@ 2005-11-03 23:26 ` Josef Weidendorfer
0 siblings, 0 replies; 20+ messages in thread
From: Josef Weidendorfer @ 2005-11-03 23:26 UTC (permalink / raw)
To: git
On Thursday 03 November 2005 23:51, Junio C Hamano wrote:
> > 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
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 22:07 ` Junio C Hamano
2005-11-03 22:33 ` Josef Weidendorfer
@ 2005-11-04 17:06 ` Daniel Barkalow
1 sibling, 0 replies; 20+ messages in thread
From: Daniel Barkalow @ 2005-11-04 17:06 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Thu, 3 Nov 2005, Junio C Hamano wrote:
> 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*
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Now What?
2005-11-03 18:51 ` Jon Loeliger
@ 2005-11-06 20:33 ` Junio C Hamano
0 siblings, 0 replies; 20+ messages in thread
From: Junio C Hamano @ 2005-11-06 20:33 UTC (permalink / raw)
To: Jon Loeliger; +Cc: git
Jon Loeliger <jdl@freescale.com> writes:
> 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.
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2005-11-06 20:33 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-03 1:30 Now What? Jon Loeliger
2005-11-03 1:43 ` Chris Shoemaker
2005-11-03 9:00 ` Junio C Hamano
2005-11-03 18:51 ` Jon Loeliger
2005-11-06 20:33 ` Junio C Hamano
2005-11-03 8:38 ` Peter Eriksen
2005-11-03 10:00 ` Junio C Hamano
2005-11-03 17:05 ` Daniel Barkalow
2005-11-03 17:27 ` Linus Torvalds
2005-11-03 18:38 ` Junio C Hamano
2005-11-03 17:30 ` Peter Eriksen
2005-11-03 22:07 ` Junio C Hamano
2005-11-03 22:33 ` Josef Weidendorfer
2005-11-04 17:06 ` Daniel Barkalow
2005-11-03 17:25 ` Linus Torvalds
2005-11-03 8:58 ` Junio C Hamano
2005-11-03 20:55 ` Junio C Hamano
2005-11-03 22:17 ` Josef Weidendorfer
2005-11-03 22:51 ` Junio C Hamano
2005-11-03 23:26 ` Josef Weidendorfer
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).