From 190f53232d1e92a57843df90e889bcfea39620d3 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Mon, 5 Jan 2009 18:35:16 +0100 Subject: rebase: learn to rebase root commit Teach git-rebase a new option --root, which instructs it to rebase the entire history leading up to . This option must be used with --onto , and causes commits that already exist in to be skipped. (Normal operation skips commits that already exist in instead.) One possible use-case is with git-svn: suppose you start hacking (perhaps offline) on a new project, but later notice you want to commit this work to SVN. You will have to rebase the entire history, including the root commit, on a (possibly empty) commit coming from git-svn, to establish a history connection. This previously had to be done by cherry-picking the root commit manually. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- t/t3412-rebase-root.sh | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100755 t/t3412-rebase-root.sh (limited to 't') diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh new file mode 100755 index 0000000000..dd919100d6 --- /dev/null +++ b/t/t3412-rebase-root.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +test_description='git rebase --root + +Tests if git rebase --root --onto can rebase the root commit. +' +. ./test-lib.sh + +test_expect_success 'prepare repository' ' + echo 1 > A && + git add A && + git commit -m 1 && + echo 2 > A && + git add A && + git commit -m 2 && + git symbolic-ref HEAD refs/heads/other && + rm .git/index && + echo 3 > B && + git add B && + git commit -m 3 && + echo 1 > A && + git add A && + git commit -m 1b && + echo 4 > B && + git add B && + git commit -m 4 +' + +test_expect_success 'rebase --root expects --onto' ' + test_must_fail git rebase --root +' + +test_expect_success 'setup pre-rebase hook' ' + mkdir -p .git/hooks && + cat >.git/hooks/pre-rebase <.git/PRE-REBASE-INPUT +EOF + chmod +x .git/hooks/pre-rebase +' +cat > expect <' ' + git checkout -b work && + git rebase --root --onto master && + git log --pretty=tformat:"%s" > rebased && + test_cmp expect rebased +' + +test_expect_success 'pre-rebase got correct input (1)' ' + test "z$(cat .git/PRE-REBASE-INPUT)" = z--root, +' + +test_expect_success 'rebase --root --onto ' ' + git branch work2 other && + git rebase --root --onto master work2 && + git log --pretty=tformat:"%s" > rebased2 && + test_cmp expect rebased2 +' + +test_expect_success 'pre-rebase got correct input (2)' ' + test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work2 +' + +test_expect_success 'setup pre-rebase hook that fails' ' + mkdir -p .git/hooks && + cat >.git/hooks/pre-rebase < Date: Fri, 2 Jan 2009 23:28:28 +0100 Subject: rebase -i: learn to rebase root commit Teach git-rebase -i a new option --root, which instructs it to rebase the entire history leading up to . This is mainly for symmetry with ordinary git-rebase; it cannot be used to edit the root commit in-place (it requires --onto ). Commits that already exist in are skipped. In the normal mode of operation, this is fairly straightforward. We run cherry-pick in a loop, and cherry-pick has supported picking the root commit since f95ebf7 (Allow cherry-picking root commits, 2008-07-04). In --preserve-merges mode, we track the mapping from old to rewritten commits and use it to update the parent list of each commit. In this case, we define 'rebase -i -p --root --onto $onto $branch' to rewrite the parent list of all root commit(s) on $branch to contain $onto instead. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- t/t3412-rebase-root.sh | 101 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) (limited to 't') diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh index dd919100d6..6359580262 100755 --- a/t/t3412-rebase-root.sh +++ b/t/t3412-rebase-root.sh @@ -67,6 +67,100 @@ test_expect_success 'pre-rebase got correct input (2)' ' test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work2 ' +test_expect_success 'rebase -i --root --onto ' ' + git checkout -b work3 other && + GIT_EDITOR=: git rebase -i --root --onto master && + git log --pretty=tformat:"%s" > rebased3 && + test_cmp expect rebased3 +' + +test_expect_success 'pre-rebase got correct input (3)' ' + test "z$(cat .git/PRE-REBASE-INPUT)" = z--root, +' + +test_expect_success 'rebase -i --root --onto ' ' + git branch work4 other && + GIT_EDITOR=: git rebase -i --root --onto master work4 && + git log --pretty=tformat:"%s" > rebased4 && + test_cmp expect rebased4 +' + +test_expect_success 'pre-rebase got correct input (4)' ' + test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work4 +' + +test_expect_success 'rebase -i -p with linear history' ' + git checkout -b work5 other && + GIT_EDITOR=: git rebase -i -p --root --onto master && + git log --pretty=tformat:"%s" > rebased5 && + test_cmp expect rebased5 +' + +test_expect_success 'pre-rebase got correct input (5)' ' + test "z$(cat .git/PRE-REBASE-INPUT)" = z--root, +' + +test_expect_success 'set up merge history' ' + git checkout other^ && + git checkout -b side && + echo 5 > C && + git add C && + git commit -m 5 && + git checkout other && + git merge side +' + +sed 's/#/ /g' > expect-side <<'EOF' +* Merge branch 'side' into other +|\## +| * 5 +* | 4 +|/## +* 3 +* 2 +* 1 +EOF + +test_expect_success 'rebase -i -p with merge' ' + git checkout -b work6 other && + GIT_EDITOR=: git rebase -i -p --root --onto master && + git log --graph --topo-order --pretty=tformat:"%s" > rebased6 && + test_cmp expect-side rebased6 +' + +test_expect_success 'set up second root and merge' ' + git symbolic-ref HEAD refs/heads/third && + rm .git/index && + rm A B C && + echo 6 > D && + git add D && + git commit -m 6 && + git checkout other && + git merge third +' + +sed 's/#/ /g' > expect-third <<'EOF' +* Merge branch 'third' into other +|\## +| * 6 +* | Merge branch 'side' into other +|\ \## +| * | 5 +* | | 4 +|/ /## +* | 3 +|/## +* 2 +* 1 +EOF + +test_expect_success 'rebase -i -p with two roots' ' + git checkout -b work7 other && + GIT_EDITOR=: git rebase -i -p --root --onto master && + git log --graph --topo-order --pretty=tformat:"%s" > rebased7 && + test_cmp expect-third rebased7 +' + test_expect_success 'setup pre-rebase hook that fails' ' mkdir -p .git/hooks && cat >.git/hooks/pre-rebase <