aboutsummaryrefslogtreecommitdiff
path: root/git-rebase.sh
diff options
context:
space:
mode:
authorRamkumar Ramachandra <artagnon@gmail.com>2013-05-12 17:26:41 +0530
committerJunio C Hamano <gitster@pobox.com>2013-05-29 10:34:54 -0700
commit587947750bd73544a6a99811f0ddfd64e1ff1445 (patch)
treeb26e7a4526e1e2a658e65e18da0ebde73474362f /git-rebase.sh
parent01a1e6465fea95c2b4303ed6c9bd14b276456f2d (diff)
downloadgit-587947750bd73544a6a99811f0ddfd64e1ff1445.tar.gz
git-587947750bd73544a6a99811f0ddfd64e1ff1445.tar.xz
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-xgit-rebase.sh45
1 files changed, 42 insertions, 3 deletions
diff --git a/git-rebase.sh b/git-rebase.sh
index f8b533d18..d0c11a910 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,