diff options
author | Ramkumar Ramachandra <artagnon@gmail.com> | 2013-05-12 17:26:41 +0530 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2013-05-29 10:34:54 -0700 |
commit | 587947750bd73544a6a99811f0ddfd64e1ff1445 (patch) | |
tree | b26e7a4526e1e2a658e65e18da0ebde73474362f /git-rebase.sh | |
parent | 01a1e6465fea95c2b4303ed6c9bd14b276456f2d (diff) | |
download | git-587947750bd73544a6a99811f0ddfd64e1ff1445.tar.gz |
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>
Diffstat (limited to 'git-rebase.sh')
-rwxr-xr-x | git-rebase.sh | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/git-rebase.sh b/git-rebase.sh index f8b533d183..d0c11a910a 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -13,6 +13,7 @@ git-rebase --continue | --abort | --skip | --edit-todo Available options are v,verbose! display a diffstat of what changed upstream q,quiet! be quiet. implies --no-stat +autostash! automatically stash/stash pop before and after onto=! rebase onto given branch instead of upstream p,preserve-merges! try to recreate merges instead of ignoring them s,strategy=! use the given merge strategy @@ -64,6 +65,7 @@ apply_dir="$GIT_DIR"/rebase-apply verbose= diffstat= test "$(git config --bool rebase.stat)" = true && diffstat=t +autostash="$(git config --bool rebase.autostash || echo false)" git_am_opt= rebase_root= force_rebase= @@ -143,6 +145,29 @@ move_to_original_branch () { esac } +finish_rebase () { + if test -f "$state_dir/autostash" + then + stash_sha1=$(cat "$state_dir/autostash") + if git stash apply $stash_sha1 2>&1 >/dev/null + then + echo "$(gettext 'Applied autostash.')" + else + ref_stash=refs/stash && + >>"$GIT_DIR/logs/$ref_stash" && + git update-ref -m "autostash" $ref_stash $stash_sha1 || + die "$(eval_gettext 'Cannot store $stash_sha1')" + + gettext 'Applying autostash resulted in conflicts. +Your changes are safe in the stash. +You can run "git stash pop" or "git stash drop" it at any time. +' + fi + fi + git gc --auto && + rm -rf "$state_dir" +} + run_specific_rebase () { if [ "$interactive_rebase" = implied ]; then GIT_EDITOR=: @@ -153,8 +178,7 @@ run_specific_rebase () { ret=$? if test $ret -eq 0 then - git gc --auto && - rm -rf "$state_dir" + finish_rebase fi exit $ret } @@ -248,6 +272,9 @@ do --stat) diffstat=t ;; + --autostash) + autostash=true + ;; -v) verbose=t diffstat=t @@ -348,7 +375,7 @@ abort) ;; esac output git reset --hard $orig_head - rm -r "$state_dir" + finish_rebase exit ;; edit-todo) @@ -487,6 +514,18 @@ case "$#" in ;; esac +if test "$autostash" = true && ! (require_clean_work_tree) 2>/dev/null +then + stash_sha1=$(git stash create "autostash") || + die "$(gettext 'Cannot autostash')" + + mkdir -p "$state_dir" && + echo $stash_sha1 >"$state_dir/autostash" && + stash_abbrev=$(git rev-parse --short $stash_sha1) && + echo "$(eval_gettext 'Created autostash: $stash_abbrev')" && + git reset --hard +fi + require_clean_work_tree "rebase" "$(gettext "Please commit or stash them.")" # Now we are rebasing commits $upstream..$orig_head (or with --root, |