git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Csaba Henk <csaba@lowlife.hu>
To: git@vger.kernel.org
Subject: git symbolic-ref vs. reflog (vs. rebase)
Date: Fri, 29 Apr 2011 15:03:52 +0000 (UTC)	[thread overview]
Message-ID: <ipek0o$l0v$1@dough.gmane.org> (raw)

"git symbolic-ref" is a dangerous command in the sense that it can
change your HEAD position without updating the reflog. Is it
intended behaviour?

I found now a case where this feature causes strange behavior.
It seems to me that either behaviour of git symbolic-ref, or the way
it is used should be changed, but I'm not sure which of these
would be the right solution.

If I'm at a detached HEAD and I do a rebase onto it, from which then
I step back with "git rebase --abort", then I seem to lose references
to the HEAD before rebase, as git reflog won't show it anymore.

This is because of two factors:

- unlike a rebase onto a branch-referred head, we don't get an
  additional reflog entry for moving to the starting position
  of the rebase (ie. we don't actually changes HEAD, nevertheless
  in the branchy case a dummy reflog entry is made for HEAD);

- upon aborting the rebase, a call is done to "git symbolic-ref"
  in the aforementioned unsafe way, ie. it changes HEAD but
  does not update reflog.

The phenomenon is illustrated by the script below. Usage:

- fist arg is the dir where the script will run (should
  not exist at invocation, script creates it).

- optional second arg is a branchname, if you give it, you'll
  see the branchy case, else you get the rebase-onto-detached
  case

Observe the following: 

- in both of branchy and detached cases, one reflog entry for
  the starting HEAD disappears from reflog output, but in the
  branchy case there are two of them before "rebase --abort"
  so you don't lose the reference;

- "rebase --abort" does not change the reflog file, but
  the reflog command's output changes, as it shows the actual HEAD
  as HEAD{0}, regardless of the last log entry.

Csaba

 * * *

bash> cat gtr.sh
#!/bin/bash -e

GIT=${GIT:-git}

if !([ $# -eq 1 ] || [ $# -eq 2 ]) || [ "$1" = -h ]; then
    echo usage: `basename $0` scratchdir [branchname]
fi

if ! [ -z $2 ]; then
    branch=$2
    bropt=-b
fi

mkdir "$1"
cd "$1"

{
$GIT init

echo master > file
$GIT add file
$GIT commit -m Master.

$GIT checkout -b topic
echo topic > file
$GIT commit -am Topic.

$GIT checkout $bropt $branch master~0
echo detached > file
$GIT commit -am 'Rebase base'.
} &>/dev/null

echo
$GIT log --all --graph --decorate --pretty=oneline
echo

set -x

$GIT hash-object .git/logs/HEAD
$GIT rebase HEAD topic || :
$GIT hash-object .git/logs/HEAD
$GIT reflog
# ruby is used to compactify the logfile,
# if you don't have ruby, comment out
# the filtering part.
cat .git/logs/HEAD | ruby -ane 'puts $F.map{|x| x[0..(x =~ /:$/ ? -1 : 7)] }.join(" ")'
$GIT rebase --abort
$GIT hash-object .git/logs/HEAD
$GIT reflog

bash> ./gtr.sh testdir

* 27a1300e35857be6357adaf6759eb8ce0818d37b (topic) Topic.
| * 5d4be82c08bf6effc906a37419220ca428834844 (HEAD) Rebase base.
|/
* 6fa006d134be4d986e1a680cac4eddd61494164a (master) Master.

+ git hash-object .git/logs/HEAD
cd15f363cf16ea3e03f5177b502de8ce3543ff21
+ git rebase HEAD topic
First, rewinding head to replay your work on top of it...
Applying: Topic.
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging file
CONFLICT (content): Merge conflict in file
Failed to merge in the changes.
Patch failed at 0001 Topic.

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

+ :
+ git hash-object .git/logs/HEAD
cd15f363cf16ea3e03f5177b502de8ce3543ff21
+ git reflog
5d4be82 HEAD@{0}: commit: Rebase base.
6fa006d HEAD@{1}: checkout: moving from topic to master~0
27a1300 HEAD@{2}: commit: Topic.
6fa006d HEAD@{3}: checkout: moving from master to topic
6fa006d HEAD@{4}: commit (initial): Master.
+ cat .git/logs/HEAD
+ ruby -ane 'puts $F.map{|x| x[0..(x =~ /:$/ ? -1 : 7)] }.join(" ")'
00000000 6fa006d1 Csaba Henk <csaba@l 13040883 +0530 commit (initial): Master.
6fa006d1 6fa006d1 Csaba Henk <csaba@l 13040883 +0530 checkout: moving from master to topic
6fa006d1 27a1300e Csaba Henk <csaba@l 13040883 +0530 commit: Topic.
27a1300e 6fa006d1 Csaba Henk <csaba@l 13040883 +0530 checkout: moving from topic to master~0
6fa006d1 5d4be82c Csaba Henk <csaba@l 13040883 +0530 commit: Rebase base.
+ git rebase --abort
HEAD is now at 27a1300 Topic.
+ git hash-object .git/logs/HEAD
cd15f363cf16ea3e03f5177b502de8ce3543ff21
+ git reflog
27a1300 HEAD@{0}: commit: Rebase base.
6fa006d HEAD@{1}: checkout: moving from topic to master~0
27a1300 HEAD@{2}: commit: Topic.
6fa006d HEAD@{3}: checkout: moving from master to topic
6fa006d HEAD@{4}: commit (initial): Master.
bash> rm -rf testdir
bash> ./gtr.sh testdir foobr

* fa0c2b339d1f048281ed7098d8d7d55a12b35154 (HEAD, foobr) Rebase base.
| * a87b990fcd5c7a109611694dcc9523d4f00ae8fe (topic) Topic.
|/
* 1e2d1c12f46105c9329479535780ec230afe7fa0 (master) Master.

+ git hash-object .git/logs/HEAD
734ae3b60eee21ee2b8b51450040389004d56e5d
+ git rebase HEAD topic
First, rewinding head to replay your work on top of it...
Applying: Topic.
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging file
CONFLICT (content): Merge conflict in file
Failed to merge in the changes.
Patch failed at 0001 Topic.

When you have resolved this problem run "git rebase --continue".
If you would prefer to skip this patch, instead run "git rebase --skip".
To restore the original branch and stop rebasing run "git rebase --abort".

+ :
+ git hash-object .git/logs/HEAD
5acf3d5f543333f549b3f9d295ed2ba91074b43d
+ git reflog
fa0c2b3 HEAD@{0}: checkout: moving from foobr to fa0c2b339d1f048281ed7098d8d7d55a12b35154^0
fa0c2b3 HEAD@{1}: commit: Rebase base.
1e2d1c1 HEAD@{2}: checkout: moving from topic to foobr
a87b990 HEAD@{3}: commit: Topic.
1e2d1c1 HEAD@{4}: checkout: moving from master to topic
1e2d1c1 HEAD@{5}: commit (initial): Master.
+ cat .git/logs/HEAD
+ ruby -ane 'puts $F.map{|x| x[0..(x =~ /:$/ ? -1 : 7)] }.join(" ")'
00000000 1e2d1c12 Csaba Henk <csaba@l 13040887 +0530 commit (initial): Master.
1e2d1c12 1e2d1c12 Csaba Henk <csaba@l 13040887 +0530 checkout: moving from master to topic
1e2d1c12 a87b990f Csaba Henk <csaba@l 13040887 +0530 commit: Topic.
a87b990f 1e2d1c12 Csaba Henk <csaba@l 13040887 +0530 checkout: moving from topic to foobr
1e2d1c12 fa0c2b33 Csaba Henk <csaba@l 13040887 +0530 commit: Rebase base.
fa0c2b33 fa0c2b33 Csaba Henk <csaba@l 13040887 +0530 checkout: moving from foobr to fa0c2b33
+ git rebase --abort
HEAD is now at a87b990 Topic.
+ git hash-object .git/logs/HEAD
5acf3d5f543333f549b3f9d295ed2ba91074b43d
+ git reflog
a87b990 HEAD@{0}: checkout: moving from foobr to fa0c2b339d1f048281ed7098d8d7d55a12b35154^0
fa0c2b3 HEAD@{1}: commit: Rebase base.
1e2d1c1 HEAD@{2}: checkout: moving from topic to foobr
a87b990 HEAD@{3}: commit: Topic.
1e2d1c1 HEAD@{4}: checkout: moving from master to topic
1e2d1c1 HEAD@{5}: commit (initial): Master.

             reply	other threads:[~2011-04-29 15:10 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-29 15:03 Csaba Henk [this message]
2011-04-29 16:19 ` git symbolic-ref vs. reflog (vs. rebase) Junio C Hamano
2011-04-29 17:21   ` Csaba Henk
2011-04-30  4:13     ` Jeff King
2011-05-02  8:46       ` Csaba Henk
2011-05-27 20:13         ` [PATCH 1/2] rebase: create HEAD reflog entry when aborting Jeff King
2011-05-27 20:16         ` [PATCH 2/2] rebase: write a reflog entry when finishing Jeff King
2011-04-29 22:48   ` git symbolic-ref vs. reflog (vs. rebase) Jeff King
2011-04-29 23:00     ` Junio C Hamano
2011-04-30  3:58       ` Jeff King
2011-05-02  8:38       ` Csaba Henk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='ipek0o$l0v$1@dough.gmane.org' \
    --to=csaba@lowlife.hu \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).