{"thread":{"id":"10573","subject":"[RFC PATCH 0/3] Starting rebase from dirty tree","startedAt":"2007-11-01T21:30:21Z","lastAt":"2007-11-12T19:51:54Z","messageCount":8,"participants":["Simon Sasburg","Junio C Hamano","Shawn O. Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"57871","messageId":"1193952624-608-1-git-send-email-Simon.Sasburg@gmail.com","threadId":"10573","inReplyTo":null,"subject":"[RFC PATCH 0/3] Starting rebase from dirty tree","fromName":"Simon Sasburg","fromEmail":"simon.sasburg@gmail.com","sentAt":"2007-11-01T21:30:21Z","receivedAt":"2007-11-01T21:30:21Z","isPatch":true,"sender":{"key":"simon.sasburg@gmail.com","avatar":null},"body":"\nThese patches allow a --dirty option for git-rebase, git-rebase--interactive, and git-svn rebase.\n\nWhen --dirty is given, starting from a dirty tree state will be allowed.\nThe difference between HEAD and the index and between the index and the working tree will be committed,\nthese commits will be undone when the rebase is completed.\n\nFor me the most often used use case is git-svn rebase one, which i use often.\nThis prevents me form having to commit+reset or stash+unstash everytime i want\nto do this in a dirty tree.\n\nI recently saw some discussion about a stash-based patch to do the same thing, and decided to share this.\nThese patches are a bit rough in some places, and mostly meant to see what others think if this way of doing this.\n\nOne advantage above using stash is that merge conflicts will be presented to the user in the same way as when doing a normal rebase.\nAlso having to explicitly ask for this behaviour with --dirty will hopefully give the user some clue that this isn't a standard operation.\n\nBut, 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.\n\nWell, comments are welcome :-)\n"},{"id":"57873","messageId":"1193952624-608-2-git-send-email-Simon.Sasburg@gmail.com","threadId":"10573","inReplyTo":"1193952624-608-1-git-send-email-Simon.Sasburg@gmail.com","subject":"[PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state.","fromName":"Simon Sasburg","fromEmail":"simon.sasburg@gmail.com","sentAt":"2007-11-01T21:30:22Z","receivedAt":"2007-11-01T21:30:22Z","isPatch":true,"sender":{"key":"simon.sasburg@gmail.com","avatar":null},"body":"This will store the difference between HEAD and the index into a commit,\nand the difference between the index and the working tree into a commit.\n\nWhen the rebase is done, it restores the index and the working tree\nby undoing these commits with git-reset.\n\nSigned-off-by: Simon Sasburg <Simon.Sasburg@gmail.com>\n---\n git-rebase.sh |   63 ++++++++++++++++++++++++++++++++++++++++++++++++--------\n 1 files changed, 54 insertions(+), 9 deletions(-)\n\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex 224cca9..c923c3b 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -42,6 +42,7 @@ To restore the original branch and stop rebasing run \\\"git rebase --abort\\\".\n unset newbase\n strategy=recursive\n do_merge=\n+fix_dirty=\n dotest=$GIT_DIR/.dotest-merge\n prec=4\n verbose=\n@@ -117,9 +118,39 @@ call_merge () {\n \n finish_rb_merge () {\n \trm -r \"$dotest\"\n+\trestore_dirty_state\n \techo \"All done.\"\n }\n \n+store_dirty_state () {\n+\techo \"Storing dirty index/working tree\"\n+\tdiff=$(git diff --cached)\n+\tcase \"$diff\" in\n+\t?*)\tgit commit -m \"REBASE--dirty: store HEAD..index diff\"\n+\t\t;;\n+\tesac\n+\tdiff=$(git diff)\n+\tcase \"$diff\" in\n+\t?*)\tgit commit -a -m \"REBASE--dirty: store index..workingtree diff\"\n+\t\t;;\n+\tesac\n+}\n+\n+restore_dirty_state () {\n+\tlastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed \"s:[^ ]* ::\")\n+\tif test \"$lastmsg\" = \"REBASE--dirty: store index..workingtree diff\"\n+\tthen\n+\t\techo \"Restoring dirty index state\"\n+\t\tgit reset --mixed HEAD^\n+\tfi\n+\tlastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed \"s:[^ ]* ::\")\n+\tif test \"$lastmsg\" = \"REBASE--dirty: store HEAD..index diff\"\n+\tthen\n+\t\techo \"Restoring dirty working dir state\"\n+\t\tgit reset --soft HEAD^\n+\tfi\n+}\n+\n is_interactive () {\n \ttest -f \"$dotest\"/interactive ||\n \twhile :; do case $#,\"$1\" in 0,|*,-i|*,--interactive) break ;; esac\n@@ -156,6 +187,10 @@ do\n \t\tgit am --resolved --3way --resolvemsg=\"$RESOLVEMSG\"\n \t\texit\n \t\t;;\n+\t--dirty)\n+\t\tdo_merge=t\n+\t\tfix_dirty=t\n+\t\t;;\n \t--skip)\n \t\tif test -d \"$dotest\"\n \t\tthen\n@@ -188,6 +223,7 @@ do\n \t\t\tdie \"No rebase in progress?\"\n \t\tfi\n \t\tgit reset --hard ORIG_HEAD\n+\t\trestore_dirty_state\n \t\texit\n \t\t;;\n \t--onto)\n@@ -253,15 +289,19 @@ else\n \tfi\n fi\n \n-# The tree must be really really clean.\n-git update-index --refresh || exit\n-diff=$(git diff-index --cached --name-status -r HEAD)\n-case \"$diff\" in\n-?*)\techo \"cannot rebase: your index is not up-to-date\"\n-\techo \"$diff\"\n-\texit 1\n-\t;;\n-esac\n+# The tree must be really really clean, unless --dirty is given.\n+if test \"$fix_dirty\" = \"\"\n+then\n+\tgit update-index --refresh || exit\n+\tdiff=$(git diff-index --cached --name-status -r HEAD)\n+\tcase \"$diff\" in\n+\t?*)\techo \"cannot rebase: your index is not up-to-date\"\n+\t\techo \"$diff\"\n+\t\texit 1\n+\t\t;;\n+\tesac\n+\t\n+fi\n \n # The upstream head must be given.  Make sure it is valid.\n upstream_name=\"$1\"\n@@ -318,6 +358,11 @@ then\n \tGIT_PAGER='' git diff --stat --summary \"$mb\" \"$onto\"\n fi\n \n+if test \"$fix_dirty\" = \"t\"\n+then\n+\tstore_dirty_state\n+fi\n+\n # Rewind the head to \"$onto\"; this saves our current head in ORIG_HEAD.\n echo \"First, rewinding head to replay your work on top of it...\"\n git-reset --hard \"$onto\"\n-- \n1.5.3.4.502.g37c97\n"},{"id":"57872","messageId":"1193952624-608-3-git-send-email-Simon.Sasburg@gmail.com","threadId":"10573","inReplyTo":"1193952624-608-2-git-send-email-Simon.Sasburg@gmail.com","subject":"[PATCH 2/3] Implement --dirty for git-rebase--interactive.","fromName":"Simon Sasburg","fromEmail":"simon.sasburg@gmail.com","sentAt":"2007-11-01T21:30:23Z","receivedAt":"2007-11-01T21:30:23Z","isPatch":true,"sender":{"key":"simon.sasburg@gmail.com","avatar":null},"body":"Signed-off-by: Simon Sasburg <Simon.Sasburg@gmail.com>\n---\n git-rebase--interactive.sh |   42 ++++++++++++++++++++++++++++++++++++++++--\n 1 files changed, 40 insertions(+), 2 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 76dc679..326076b 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -25,6 +25,7 @@ REWRITTEN=\"$DOTEST\"/rewritten\n PRESERVE_MERGES=\n STRATEGY=\n VERBOSE=\n+FIX_DIRTY=\n test -d \"$REWRITTEN\" && PRESERVE_MERGES=t\n test -f \"$DOTEST\"/strategy && STRATEGY=\"$(cat \"$DOTEST\"/strategy)\"\n test -f \"$DOTEST\"/verbose && VERBOSE=t\n@@ -56,6 +57,35 @@ require_clean_work_tree () {\n \tdie \"Working tree is dirty\"\n }\n \n+store_dirty_state () {\n+\techo \"Storing dirty index/working tree\"\n+\tdiff=$(git diff --cached)\n+\tcase \"$diff\" in\n+\t?*)\tgit commit -m \"REBASE--dirty: store HEAD..index diff\"\n+\t\t;;\n+\tesac\n+\tdiff=$(git diff)\n+\tcase \"$diff\" in\n+\t?*)\tgit commit -a -m \"REBASE--dirty: store index..workingtree diff\"\n+\t\t;;\n+\tesac\n+}\n+\n+restore_dirty_state () {\n+\tlastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed \"s:[^ ]* ::\")\n+\tif test \"$lastmsg\" = \"REBASE--dirty: store index..workingtree diff\"\n+\tthen\n+\t\techo \"Restoring dirty index state\"\n+\t\tgit reset --mixed HEAD^\n+\tfi\n+\tlastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed \"s:[^ ]* ::\")\n+\tif test \"$lastmsg\" = \"REBASE--dirty: store HEAD..index diff\"\n+\tthen\n+\t\techo \"Restoring dirty working dir state\"\n+\t\tgit reset --soft HEAD^\n+\tfi\n+}\n+\n ORIG_REFLOG_ACTION=\"$GIT_REFLOG_ACTION\"\n \n comment_for_reflog () {\n@@ -329,6 +359,7 @@ do_next () {\n \t\ttest ! -f \"$DOTEST\"/verbose ||\n \t\t\tgit diff-tree --stat $(cat \"$DOTEST\"/head)..HEAD\n \t} &&\n+\trestore_dirty_state &&\n \trm -rf \"$DOTEST\" &&\n \tgit gc --auto &&\n \twarn \"Successfully rebased and updated $HEADNAME.\"\n@@ -378,6 +409,7 @@ do\n \t\t\t;;\n \t\tesac &&\n \t\toutput git reset --hard $HEAD &&\n+\t\trestore_dirty_state &&\n \t\trm -rf \"$DOTEST\"\n \t\texit\n \t\t;;\n@@ -417,6 +449,9 @@ do\n \t''|-h)\n \t\tusage\n \t\t;;\n+\t--dirty)\n+\t\tFIX_DIRTY=t\n+\t\t;;\n \t*)\n \t\ttest -d \"$DOTEST\" &&\n \t\t\tdie \"Interactive rebase already started\"\n@@ -435,7 +470,7 @@ do\n \t\t\t;;\n \t\tesac\n \n-\t\trequire_clean_work_tree\n+\t\ttest \"$FIX_DIRTY\" = \"t\" || require_clean_work_tree\n \n \t\tif test ! -z \"$2\"\n \t\tthen\n@@ -445,9 +480,12 @@ do\n \t\t\t\tdie \"Could not checkout $2\"\n \t\tfi\n \n-\t\tHEAD=$(git rev-parse --verify HEAD) || die \"No HEAD?\"\n \t\tUPSTREAM=$(git rev-parse --verify \"$1\") || die \"Invalid base\"\n \n+\t\ttest \"$FIX_DIRTY\" = \"t\" && store_dirty_state\n+\n+\t\tHEAD=$(git rev-parse --verify HEAD) || die \"No HEAD?\"\n+\n \t\tmkdir \"$DOTEST\" || die \"Could not create temporary $DOTEST\"\n \n \t\ttest -z \"$ONTO\" && ONTO=$UPSTREAM\n-- \n1.5.3.4.502.g37c97\n"},{"id":"57874","messageId":"1193952624-608-4-git-send-email-Simon.Sasburg@gmail.com","threadId":"10573","inReplyTo":"1193952624-608-3-git-send-email-Simon.Sasburg@gmail.com","subject":"[PATCH 3/3] Make git-svn rebase --dirty pass along --dirty to git-rebase.","fromName":"Simon Sasburg","fromEmail":"simon.sasburg@gmail.com","sentAt":"2007-11-01T21:30:24Z","receivedAt":"2007-11-01T21:30:24Z","isPatch":true,"sender":{"key":"simon.sasburg@gmail.com","avatar":null},"body":"Signed-off-by: Simon Sasburg <Simon.Sasburg@gmail.com>\n---\n git-svn.perl |   16 +++++++++++-----\n 1 files changed, 11 insertions(+), 5 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex 22bb47b..5898a26 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -63,7 +63,7 @@ my ($_stdin, $_help, $_edit,\n \t$_message, $_file,\n \t$_template, $_shared,\n \t$_version, $_fetch_all, $_no_rebase,\n-\t$_merge, $_strategy, $_dry_run, $_local,\n+\t$_merge, $_strategy, $_dry_run, $_local, $_dirty,\n \t$_prefix, $_no_checkout, $_verbose);\n $Git::SVN::_follow_parent = 1;\n my %remote_opts = ( 'username=s' => \\$Git::SVN::Prompt::_username,\n@@ -169,6 +169,7 @@ my %cmd = (\n \t\t\t  'verbose|v' => \\$_verbose,\n \t\t\t  'strategy|s=s' => \\$_strategy,\n \t\t\t  'local|l' => \\$_local,\n+\t\t\t  'dirty|d' => \\$_dirty,\n \t\t\t  'fetch-all|all' => \\$_fetch_all,\n \t\t\t  %fc_opts } ],\n \t'commit-diff' => [ \\&cmd_commit_diff,\n@@ -482,16 +483,20 @@ sub cmd_find_rev {\n }\n \n sub cmd_rebase {\n-\tcommand_noisy(qw/update-index --refresh/);\n+\tunless ($_dirty) {\n+\t\tcommand_noisy(qw/update-index --refresh/);\n+\t}\n \tmy ($url, $rev, $uuid, $gs) = working_head_info('HEAD');\n \tunless ($gs) {\n \t\tdie \"Unable to determine upstream SVN information from \",\n \t\t    \"working tree history\\n\";\n \t}\n \tif (command(qw/diff-index HEAD --/)) {\n-\t\tprint STDERR \"Cannot rebase with uncommited changes:\\n\";\n-\t\tcommand_noisy('status');\n-\t\texit 1;\n+\t\tunless ($_dirty) {\n+\t\t\tprint STDERR \"Cannot rebase with uncommited changes:\\n\";\n+\t\t\tcommand_noisy('status');\n+\t\t\texit 1;\n+\t\t}\n \t}\n \tunless ($_local) {\n \t\t$_fetch_all ? $gs->fetch_all : $gs->fetch;\n@@ -697,6 +702,7 @@ sub rebase_cmd {\n \tpush @cmd, '-v' if $_verbose;\n \tpush @cmd, qw/--merge/ if $_merge;\n \tpush @cmd, \"--strategy=$_strategy\" if $_strategy;\n+\tpush @cmd, \"--dirty\" if $_dirty;\n \t@cmd;\n }\n \n-- \n1.5.3.4.502.g37c97\n"},{"id":"57889","messageId":"7vmytx8upi.fsf@gitster.siamese.dyndns.org","threadId":"10573","inReplyTo":"1193952624-608-2-git-send-email-Simon.Sasburg@gmail.com","subject":"Re: [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-01T22:30:33Z","receivedAt":"2007-11-01T22:30:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Doesn't this have the exact same problem with the one in 'next'\nthat uses \"git-stash create\", which Shawn said he was upset\nabout, and I said I will revert?\n\nFYI, this is what I wrote in the log for the revert.\n\ncommit 0f49327c9755b6575b447f79b540749d231cb26d\nAuthor: Junio C Hamano <gitster@pobox.com>\nDate:   Thu Nov 1 13:46:20 2007 -0700\n\n    Revert \"rebase: allow starting from a dirty tree.\"\n    \n    This reverts commit 6c9ad166dbbf9e5a0c09450b892151dbec49b8dc.\n    Allowing rebase to start in a dirty tree might have been a worthy\n    goal, but it is not necessarily always wanted (some people prefer\n    to be reminded that the state is dirty, and think about the next\n    action that may not be to stash and proceed).  Furthermore, depending\n    on the nature of local changes, unstashing the dirty state on top of\n    the rebased result is not always desirable.\n    \n    Signed-off-by: Junio C Hamano <gitster@pobox.com>\n"},{"id":"57890","messageId":"7vir4l8ug4.fsf@gitster.siamese.dyndns.org","threadId":"10573","inReplyTo":"7vmytx8upi.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-01T22:36:11Z","receivedAt":"2007-11-01T22:36:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Doesn't this have the exact same problem with the one in 'next'\n> that uses \"git-stash create\", which Shawn said he was upset\n> about, and I said I will revert?\n\nSorry, --dirty is not the default, which changes everything.\nForget what I said, sorry for the noise.\n"},{"id":"57926","messageId":"20071102050830.GA14735@spearce.org","threadId":"10573","inReplyTo":"7vir4l8ug4.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/3] Introduce --dirty option to git-rebase, allowing you to start from a dirty state.","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2007-11-02T05:08:30Z","receivedAt":"2007-11-02T05:08:30Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n> \n> > Doesn't this have the exact same problem with the one in 'next'\n> > that uses \"git-stash create\", which Shawn said he was upset\n> > about, and I said I will revert?\n> \n> Sorry, --dirty is not the default, which changes everything.\n> Forget what I said, sorry for the noise.\n\nI'm happy with having --dirty, but AS AN OPTION.  Heck, I'd probably\nuse it sometimes, but only if it also reapplies the stash after\nthe rebase is complete.  But doing that stash/apply automatically\nis really freaking annoying.\n\nFor the same reasons why I like git-checkout not defaulting to -m.\nI want Git to stop by default if I'm about to possibly go into a\ncommand that is going to cause conflicts, as I may not be ready to\ndeal with them right now.\n\n-- \nShawn.\n"},{"id":"59557","messageId":"7vpryf2qed.fsf@gitster.siamese.dyndns.org","threadId":"10573","inReplyTo":"1193952624-608-3-git-send-email-Simon.Sasburg@gmail.com","subject":"Re: [PATCH 2/3] Implement --dirty for git-rebase--interactive.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-12T19:51:54Z","receivedAt":"2007-11-12T19:51:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Simon Sasburg <simon.sasburg@gmail.com> writes:\n\n> +restore_dirty_state () {\n> +\tlastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed \"s:[^ ]* ::\")\n> +\tif test \"$lastmsg\" = \"REBASE--dirty: store index..workingtree diff\"\n> +\tthen\n> +\t\techo \"Restoring dirty index state\"\n> +\t\tgit reset --mixed HEAD^\n> +\tfi\n> +\tlastmsg=$(git-rev-list HEAD^..HEAD --pretty=oneline | sed \"s:[^ ]* ::\")\n> +\tif test \"$lastmsg\" = \"REBASE--dirty: store HEAD..index diff\"\n> +\tthen\n> +\t\techo \"Restoring dirty working dir state\"\n> +\t\tgit reset --soft HEAD^\n> +\tfi\n> +}\n\nThis forces the user to pay the two rev-list overhead, even when\nrunning rebase without --dirty option.  Can we avoid paying any,\nwhen not giving the option?\n\nAlso it pollutes the reflog of the branch, but that won't be a\nhuge issue with Dscho's \"detach HEAD while rebasing\" patch.\n"}]}