* [RFC PATCH 0/3] Starting rebase from dirty tree
@ 2007-11-01 21:30 Simon Sasburg
2007-11-01 21:30 ` [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state Simon Sasburg
0 siblings, 1 reply; 8+ messages in thread
From: Simon Sasburg @ 2007-11-01 21:30 UTC (permalink / raw)
To: gitster; +Cc: git
These patches allow a --dirty option for git-rebase, git-rebase--interactive, and git-svn rebase.
When --dirty is given, starting from a dirty tree state will be allowed.
The difference between HEAD and the index and between the index and the working tree will be committed,
these commits will be undone when the rebase is completed.
For me the most often used use case is git-svn rebase one, which i use often.
This prevents me form having to commit+reset or stash+unstash everytime i want
to do this in a dirty tree.
I recently saw some discussion about a stash-based patch to do the same thing, and decided to share this.
These patches are a bit rough in some places, and mostly meant to see what others think if this way of doing this.
One advantage above using stash is that merge conflicts will be presented to the user in the same way as when doing a normal rebase.
Also having to explicitly ask for this behaviour with --dirty will hopefully give the user some clue that this isn't a standard operation.
But, in the rebase--interactive case, it allows the user to shoot himself in the foot by re-ordering the commits such that the temporary ones aren't at the end anymore.
Well, comments are welcome :-)
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state.
2007-11-01 21:30 [RFC PATCH 0/3] Starting rebase from dirty tree Simon Sasburg
@ 2007-11-01 21:30 ` Simon Sasburg
2007-11-01 21:30 ` [PATCH 2/3] Implement --dirty for git-rebase--interactive Simon Sasburg
2007-11-01 22:30 ` [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state Junio C Hamano
0 siblings, 2 replies; 8+ messages in thread
From: Simon Sasburg @ 2007-11-01 21:30 UTC (permalink / raw)
To: gitster; +Cc: git, Simon Sasburg
This will store the difference between HEAD and the index into a commit,
and the difference between the index and the working tree into a commit.
When the rebase is done, it restores the index and the working tree
by undoing these commits with git-reset.
Signed-off-by: Simon Sasburg <Simon.Sasburg@gmail.com>
---
git-rebase.sh | 63 ++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 54 insertions(+), 9 deletions(-)
diff --git a/git-rebase.sh b/git-rebase.sh
index 224cca9..c923c3b 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -42,6 +42,7 @@ To restore the original branch and stop rebasing run \"git rebase --abort\".
unset newbase
strategy=recursive
do_merge=
+fix_dirty=
dotest=$GIT_DIR/.dotest-merge
prec=4
verbose=
@@ -117,9 +118,39 @@ call_merge () {
finish_rb_merge () {
rm -r "$dotest"
+ restore_dirty_state
echo "All done."
}
+store_dirty_state () {
+ echo "Storing dirty index/working tree"
+ diff=$(git diff --cached)
+ case "$diff" in
+ ?*) git commit -m "REBASE--dirty: store HEAD..index diff"
+ ;;
+ esac
+ diff=$(git diff)
+ case "$diff" in
+ ?*) git commit -a -m "REBASE--dirty: store index..workingtree diff"
+ ;;
+ esac
+}
+
+restore_dirty_state () {
+ lastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed "s:[^ ]* ::")
+ if test "$lastmsg" = "REBASE--dirty: store index..workingtree diff"
+ then
+ echo "Restoring dirty index state"
+ git reset --mixed HEAD^
+ fi
+ lastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed "s:[^ ]* ::")
+ if test "$lastmsg" = "REBASE--dirty: store HEAD..index diff"
+ then
+ echo "Restoring dirty working dir state"
+ git reset --soft HEAD^
+ fi
+}
+
is_interactive () {
test -f "$dotest"/interactive ||
while :; do case $#,"$1" in 0,|*,-i|*,--interactive) break ;; esac
@@ -156,6 +187,10 @@ do
git am --resolved --3way --resolvemsg="$RESOLVEMSG"
exit
;;
+ --dirty)
+ do_merge=t
+ fix_dirty=t
+ ;;
--skip)
if test -d "$dotest"
then
@@ -188,6 +223,7 @@ do
die "No rebase in progress?"
fi
git reset --hard ORIG_HEAD
+ restore_dirty_state
exit
;;
--onto)
@@ -253,15 +289,19 @@ else
fi
fi
-# The tree must be really really clean.
-git update-index --refresh || exit
-diff=$(git diff-index --cached --name-status -r HEAD)
-case "$diff" in
-?*) echo "cannot rebase: your index is not up-to-date"
- echo "$diff"
- exit 1
- ;;
-esac
+# The tree must be really really clean, unless --dirty is given.
+if test "$fix_dirty" = ""
+then
+ git update-index --refresh || exit
+ diff=$(git diff-index --cached --name-status -r HEAD)
+ case "$diff" in
+ ?*) echo "cannot rebase: your index is not up-to-date"
+ echo "$diff"
+ exit 1
+ ;;
+ esac
+
+fi
# The upstream head must be given. Make sure it is valid.
upstream_name="$1"
@@ -318,6 +358,11 @@ then
GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
fi
+if test "$fix_dirty" = "t"
+then
+ store_dirty_state
+fi
+
# Rewind the head to "$onto"; this saves our current head in ORIG_HEAD.
echo "First, rewinding head to replay your work on top of it..."
git-reset --hard "$onto"
--
1.5.3.4.502.g37c97
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/3] Implement --dirty for git-rebase--interactive.
2007-11-01 21:30 ` [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state Simon Sasburg
@ 2007-11-01 21:30 ` Simon Sasburg
2007-11-01 21:30 ` [PATCH 3/3] Make git-svn rebase --dirty pass along --dirty to git-rebase Simon Sasburg
2007-11-12 19:51 ` [PATCH 2/3] Implement --dirty for git-rebase--interactive Junio C Hamano
2007-11-01 22:30 ` [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state Junio C Hamano
1 sibling, 2 replies; 8+ messages in thread
From: Simon Sasburg @ 2007-11-01 21:30 UTC (permalink / raw)
To: gitster; +Cc: git, Simon Sasburg
Signed-off-by: Simon Sasburg <Simon.Sasburg@gmail.com>
---
git-rebase--interactive.sh | 42 ++++++++++++++++++++++++++++++++++++++++--
1 files changed, 40 insertions(+), 2 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 76dc679..326076b 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -25,6 +25,7 @@ REWRITTEN="$DOTEST"/rewritten
PRESERVE_MERGES=
STRATEGY=
VERBOSE=
+FIX_DIRTY=
test -d "$REWRITTEN" && PRESERVE_MERGES=t
test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
test -f "$DOTEST"/verbose && VERBOSE=t
@@ -56,6 +57,35 @@ require_clean_work_tree () {
die "Working tree is dirty"
}
+store_dirty_state () {
+ echo "Storing dirty index/working tree"
+ diff=$(git diff --cached)
+ case "$diff" in
+ ?*) git commit -m "REBASE--dirty: store HEAD..index diff"
+ ;;
+ esac
+ diff=$(git diff)
+ case "$diff" in
+ ?*) git commit -a -m "REBASE--dirty: store index..workingtree diff"
+ ;;
+ esac
+}
+
+restore_dirty_state () {
+ lastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed "s:[^ ]* ::")
+ if test "$lastmsg" = "REBASE--dirty: store index..workingtree diff"
+ then
+ echo "Restoring dirty index state"
+ git reset --mixed HEAD^
+ fi
+ lastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed "s:[^ ]* ::")
+ if test "$lastmsg" = "REBASE--dirty: store HEAD..index diff"
+ then
+ echo "Restoring dirty working dir state"
+ git reset --soft HEAD^
+ fi
+}
+
ORIG_REFLOG_ACTION="$GIT_REFLOG_ACTION"
comment_for_reflog () {
@@ -329,6 +359,7 @@ do_next () {
test ! -f "$DOTEST"/verbose ||
git diff-tree --stat $(cat "$DOTEST"/head)..HEAD
} &&
+ restore_dirty_state &&
rm -rf "$DOTEST" &&
git gc --auto &&
warn "Successfully rebased and updated $HEADNAME."
@@ -378,6 +409,7 @@ do
;;
esac &&
output git reset --hard $HEAD &&
+ restore_dirty_state &&
rm -rf "$DOTEST"
exit
;;
@@ -417,6 +449,9 @@ do
''|-h)
usage
;;
+ --dirty)
+ FIX_DIRTY=t
+ ;;
*)
test -d "$DOTEST" &&
die "Interactive rebase already started"
@@ -435,7 +470,7 @@ do
;;
esac
- require_clean_work_tree
+ test "$FIX_DIRTY" = "t" || require_clean_work_tree
if test ! -z "$2"
then
@@ -445,9 +480,12 @@ do
die "Could not checkout $2"
fi
- HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?"
UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
+ test "$FIX_DIRTY" = "t" && store_dirty_state
+
+ HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?"
+
mkdir "$DOTEST" || die "Could not create temporary $DOTEST"
test -z "$ONTO" && ONTO=$UPSTREAM
--
1.5.3.4.502.g37c97
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/3] Make git-svn rebase --dirty pass along --dirty to git-rebase.
2007-11-01 21:30 ` [PATCH 2/3] Implement --dirty for git-rebase--interactive Simon Sasburg
@ 2007-11-01 21:30 ` Simon Sasburg
2007-11-12 19:51 ` [PATCH 2/3] Implement --dirty for git-rebase--interactive Junio C Hamano
1 sibling, 0 replies; 8+ messages in thread
From: Simon Sasburg @ 2007-11-01 21:30 UTC (permalink / raw)
To: gitster; +Cc: git, Simon Sasburg
Signed-off-by: Simon Sasburg <Simon.Sasburg@gmail.com>
---
git-svn.perl | 16 +++++++++++-----
1 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/git-svn.perl b/git-svn.perl
index 22bb47b..5898a26 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -63,7 +63,7 @@ my ($_stdin, $_help, $_edit,
$_message, $_file,
$_template, $_shared,
$_version, $_fetch_all, $_no_rebase,
- $_merge, $_strategy, $_dry_run, $_local,
+ $_merge, $_strategy, $_dry_run, $_local, $_dirty,
$_prefix, $_no_checkout, $_verbose);
$Git::SVN::_follow_parent = 1;
my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
@@ -169,6 +169,7 @@ my %cmd = (
'verbose|v' => \$_verbose,
'strategy|s=s' => \$_strategy,
'local|l' => \$_local,
+ 'dirty|d' => \$_dirty,
'fetch-all|all' => \$_fetch_all,
%fc_opts } ],
'commit-diff' => [ \&cmd_commit_diff,
@@ -482,16 +483,20 @@ sub cmd_find_rev {
}
sub cmd_rebase {
- command_noisy(qw/update-index --refresh/);
+ unless ($_dirty) {
+ command_noisy(qw/update-index --refresh/);
+ }
my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
unless ($gs) {
die "Unable to determine upstream SVN information from ",
"working tree history\n";
}
if (command(qw/diff-index HEAD --/)) {
- print STDERR "Cannot rebase with uncommited changes:\n";
- command_noisy('status');
- exit 1;
+ unless ($_dirty) {
+ print STDERR "Cannot rebase with uncommited changes:\n";
+ command_noisy('status');
+ exit 1;
+ }
}
unless ($_local) {
$_fetch_all ? $gs->fetch_all : $gs->fetch;
@@ -697,6 +702,7 @@ sub rebase_cmd {
push @cmd, '-v' if $_verbose;
push @cmd, qw/--merge/ if $_merge;
push @cmd, "--strategy=$_strategy" if $_strategy;
+ push @cmd, "--dirty" if $_dirty;
@cmd;
}
--
1.5.3.4.502.g37c97
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state.
2007-11-01 21:30 ` [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state Simon Sasburg
2007-11-01 21:30 ` [PATCH 2/3] Implement --dirty for git-rebase--interactive Simon Sasburg
@ 2007-11-01 22:30 ` Junio C Hamano
2007-11-01 22:36 ` Junio C Hamano
1 sibling, 1 reply; 8+ messages in thread
From: Junio C Hamano @ 2007-11-01 22:30 UTC (permalink / raw)
To: Simon Sasburg; +Cc: gitster, git
Doesn't this have the exact same problem with the one in 'next'
that uses "git-stash create", which Shawn said he was upset
about, and I said I will revert?
FYI, this is what I wrote in the log for the revert.
commit 0f49327c9755b6575b447f79b540749d231cb26d
Author: Junio C Hamano <gitster@pobox.com>
Date: Thu Nov 1 13:46:20 2007 -0700
Revert "rebase: allow starting from a dirty tree."
This reverts commit 6c9ad166dbbf9e5a0c09450b892151dbec49b8dc.
Allowing rebase to start in a dirty tree might have been a worthy
goal, but it is not necessarily always wanted (some people prefer
to be reminded that the state is dirty, and think about the next
action that may not be to stash and proceed). Furthermore, depending
on the nature of local changes, unstashing the dirty state on top of
the rebased result is not always desirable.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state.
2007-11-01 22:30 ` [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state Junio C Hamano
@ 2007-11-01 22:36 ` Junio C Hamano
2007-11-02 5:08 ` Shawn O. Pearce
0 siblings, 1 reply; 8+ messages in thread
From: Junio C Hamano @ 2007-11-01 22:36 UTC (permalink / raw)
To: Simon Sasburg; +Cc: gitster, git
Junio C Hamano <gitster@pobox.com> writes:
> Doesn't this have the exact same problem with the one in 'next'
> that uses "git-stash create", which Shawn said he was upset
> about, and I said I will revert?
Sorry, --dirty is not the default, which changes everything.
Forget what I said, sorry for the noise.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state.
2007-11-01 22:36 ` Junio C Hamano
@ 2007-11-02 5:08 ` Shawn O. Pearce
0 siblings, 0 replies; 8+ messages in thread
From: Shawn O. Pearce @ 2007-11-02 5:08 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Simon Sasburg, git
Junio C Hamano <gitster@pobox.com> wrote:
> Junio C Hamano <gitster@pobox.com> writes:
>
> > Doesn't this have the exact same problem with the one in 'next'
> > that uses "git-stash create", which Shawn said he was upset
> > about, and I said I will revert?
>
> Sorry, --dirty is not the default, which changes everything.
> Forget what I said, sorry for the noise.
I'm happy with having --dirty, but AS AN OPTION. Heck, I'd probably
use it sometimes, but only if it also reapplies the stash after
the rebase is complete. But doing that stash/apply automatically
is really freaking annoying.
For the same reasons why I like git-checkout not defaulting to -m.
I want Git to stop by default if I'm about to possibly go into a
command that is going to cause conflicts, as I may not be ready to
deal with them right now.
--
Shawn.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/3] Implement --dirty for git-rebase--interactive.
2007-11-01 21:30 ` [PATCH 2/3] Implement --dirty for git-rebase--interactive Simon Sasburg
2007-11-01 21:30 ` [PATCH 3/3] Make git-svn rebase --dirty pass along --dirty to git-rebase Simon Sasburg
@ 2007-11-12 19:51 ` Junio C Hamano
1 sibling, 0 replies; 8+ messages in thread
From: Junio C Hamano @ 2007-11-12 19:51 UTC (permalink / raw)
To: Simon Sasburg; +Cc: git
Simon Sasburg <simon.sasburg@gmail.com> writes:
> +restore_dirty_state () {
> + lastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed "s:[^ ]* ::")
> + if test "$lastmsg" = "REBASE--dirty: store index..workingtree diff"
> + then
> + echo "Restoring dirty index state"
> + git reset --mixed HEAD^
> + fi
> + lastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed "s:[^ ]* ::")
> + if test "$lastmsg" = "REBASE--dirty: store HEAD..index diff"
> + then
> + echo "Restoring dirty working dir state"
> + git reset --soft HEAD^
> + fi
> +}
This forces the user to pay the two rev-list overhead, even when
running rebase without --dirty option. Can we avoid paying any,
when not giving the option?
Also it pollutes the reflog of the branch, but that won't be a
huge issue with Dscho's "detach HEAD while rebasing" patch.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2007-11-12 19:52 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-01 21:30 [RFC PATCH 0/3] Starting rebase from dirty tree Simon Sasburg
2007-11-01 21:30 ` [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state Simon Sasburg
2007-11-01 21:30 ` [PATCH 2/3] Implement --dirty for git-rebase--interactive Simon Sasburg
2007-11-01 21:30 ` [PATCH 3/3] Make git-svn rebase --dirty pass along --dirty to git-rebase Simon Sasburg
2007-11-12 19:51 ` [PATCH 2/3] Implement --dirty for git-rebase--interactive Junio C Hamano
2007-11-01 22:30 ` [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state Junio C Hamano
2007-11-01 22:36 ` Junio C Hamano
2007-11-02 5:08 ` Shawn O. Pearce
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).