-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rebase: implement --[no-]autostash and rebase.autostash
This new feature allows a rebase to be executed on a dirty worktree or index. It works by creating a temporary "dangling merge commit" out of the worktree and index changes (via 'git stash create'), and automatically applying it after a successful rebase or abort. rebase stores the SHA-1 hex of the temporary merge commit, along with the rest of the rebase state, in either .git/{rebase-merge,rebase-apply}/autostash depending on the kind of rebase. Since $state_dir is automatically removed at the end of a successful rebase or abort, so is the autostash. The advantage of this approach is that we do not affect the normal stash's reflogs, making the autostash invisible to the end-user. This means that you can use 'git stash' during a rebase as usual. When the autostash application results in a conflict, we push $state_dir/autostash onto the normal stash and remove $state_dir ending the rebase. The user can inspect the stash, and pop or drop at any time. Most significantly, this feature means that a caller like pull (with pull.rebase set to true) can easily be patched to remove the require_clean_work_tree restriction. Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
- Loading branch information
Ramkumar Ramachandra
authored and
Junio C Hamano
committed
May 29, 2013
1 parent
01a1e64
commit 5879477
Showing
4 changed files
with
208 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
#!/bin/sh | ||
# | ||
# Copyright (c) 2013 Ramkumar Ramachandra | ||
# | ||
|
||
test_description='git rebase --autostash tests' | ||
. ./test-lib.sh | ||
|
||
test_expect_success setup ' | ||
echo hello-world >file0 && | ||
git add . && | ||
test_tick && | ||
git commit -m "initial commit" && | ||
git checkout -b feature-branch && | ||
echo another-hello >file1 && | ||
echo goodbye >file2 && | ||
git add . && | ||
test_tick && | ||
git commit -m "second commit" && | ||
echo final-goodbye >file3 && | ||
git add . && | ||
test_tick && | ||
git commit -m "third commit" && | ||
git checkout -b unrelated-onto-branch master && | ||
echo unrelated >file4 && | ||
git add . && | ||
test_tick && | ||
git commit -m "unrelated commit" && | ||
git checkout -b related-onto-branch master && | ||
echo conflicting-change >file2 && | ||
git add . && | ||
test_tick && | ||
git commit -m "related commit" | ||
' | ||
|
||
testrebase() { | ||
type=$1 | ||
dotest=$2 | ||
|
||
test_expect_success "rebase$type: dirty worktree, non-conflicting rebase" ' | ||
test_config rebase.autostash true && | ||
git reset --hard && | ||
git checkout -b rebased-feature-branch feature-branch && | ||
test_when_finished git branch -D rebased-feature-branch && | ||
echo dirty >>file3 && | ||
git rebase$type unrelated-onto-branch && | ||
grep unrelated file4 && | ||
grep dirty file3 && | ||
git checkout feature-branch | ||
' | ||
|
||
test_expect_success "rebase$type: dirty index, non-conflicting rebase" ' | ||
test_config rebase.autostash true && | ||
git reset --hard && | ||
git checkout -b rebased-feature-branch feature-branch && | ||
test_when_finished git branch -D rebased-feature-branch && | ||
echo dirty >>file3 && | ||
git add file3 && | ||
git rebase$type unrelated-onto-branch && | ||
grep unrelated file4 && | ||
grep dirty file3 && | ||
git checkout feature-branch | ||
' | ||
|
||
test_expect_success "rebase$type: conflicting rebase" ' | ||
test_config rebase.autostash true && | ||
git reset --hard && | ||
git checkout -b rebased-feature-branch feature-branch && | ||
test_when_finished git branch -D rebased-feature-branch && | ||
echo dirty >>file3 && | ||
test_must_fail git rebase$type related-onto-branch && | ||
test_path_is_file $dotest/autostash && | ||
! grep dirty file3 && | ||
rm -rf $dotest && | ||
git reset --hard && | ||
git checkout feature-branch | ||
' | ||
|
||
test_expect_success "rebase$type: --continue" ' | ||
test_config rebase.autostash true && | ||
git reset --hard && | ||
git checkout -b rebased-feature-branch feature-branch && | ||
test_when_finished git branch -D rebased-feature-branch && | ||
echo dirty >>file3 && | ||
test_must_fail git rebase$type related-onto-branch && | ||
test_path_is_file $dotest/autostash && | ||
! grep dirty file3 && | ||
echo "conflicting-plus-goodbye" >file2 && | ||
git add file2 && | ||
git rebase --continue && | ||
test_path_is_missing $dotest/autostash && | ||
grep dirty file3 && | ||
git checkout feature-branch | ||
' | ||
|
||
test_expect_success "rebase$type: --skip" ' | ||
test_config rebase.autostash true && | ||
git reset --hard && | ||
git checkout -b rebased-feature-branch feature-branch && | ||
test_when_finished git branch -D rebased-feature-branch && | ||
echo dirty >>file3 && | ||
test_must_fail git rebase$type related-onto-branch && | ||
test_path_is_file $dotest/autostash && | ||
! grep dirty file3 && | ||
git rebase --skip && | ||
test_path_is_missing $dotest/autostash && | ||
grep dirty file3 && | ||
git checkout feature-branch | ||
' | ||
|
||
test_expect_success "rebase$type: --abort" ' | ||
test_config rebase.autostash true && | ||
git reset --hard && | ||
git checkout -b rebased-feature-branch feature-branch && | ||
test_when_finished git branch -D rebased-feature-branch && | ||
echo dirty >>file3 && | ||
test_must_fail git rebase$type related-onto-branch && | ||
test_path_is_file $dotest/autostash && | ||
! grep dirty file3 && | ||
git rebase --abort && | ||
test_path_is_missing $dotest/autostash && | ||
grep dirty file3 && | ||
git checkout feature-branch | ||
' | ||
|
||
test_expect_success "rebase$type: non-conflicting rebase, conflicting stash" ' | ||
test_config rebase.autostash true && | ||
git reset --hard && | ||
git checkout -b rebased-feature-branch feature-branch && | ||
test_when_finished git branch -D rebased-feature-branch && | ||
echo dirty >file4 && | ||
git add file4 && | ||
git rebase$type unrelated-onto-branch && | ||
test_path_is_missing $dotest && | ||
git reset --hard && | ||
grep unrelated file4 && | ||
! grep dirty file4 && | ||
git checkout feature-branch && | ||
git stash pop && | ||
grep dirty file4 | ||
' | ||
} | ||
|
||
testrebase "" .git/rebase-apply | ||
testrebase " --merge" .git/rebase-merge | ||
testrebase " --interactive" .git/rebase-merge | ||
|
||
test_done |