From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
For the past two months, I have been working on refactoring the rebase
code. See [1] for background information. I have been trying to polish
the patch set for some time, but now I don't think I will get much
further without your help.
My goals with this series were:
(1) Make it easier to add new features to git rebase by reducing the
amount of duplicated code. FWIW, this series removes about 140 lines
non-test code.
(2) Make the behavior (towards the user) more consistent between
interactive and non-interactive rebase. This mainly involves error
messages and command line options.
While not being a goal from the beginning, I have also tried to make
the code more readable. This is of course very subjective, so we'll
see - maybe in your eyes I just made things worse :-).
At a high level, I tried to do what was suggested by Johannes Sixt in
the second entry on [1], namely
"... to write a command line processor, git-rebase.sh, that sets shell
variables from options that it collects from various sources, then
dispatches to one of git-rebase--interactive.sh, git-rebase--merge.sh,
or git-rebase--am.sh (the latter two would be stripped-down copies of
the current git-rebase.sh)."
Patches 01-04 try to make git-rebase.sh more readable and extensible
by factoring out the code that reads the saved state from
.git/rebase-apply or .git/rebase-merge.
Patches 05-09 set the stage for further refactoring by aligning
git-rebase.sh and git-rebase--interactive.sh.
Patches 10-16 factor out parts from git-rebase--interactive.sh and let
it rely on the corresponding code in git-rebase.sh.
Patch 17 just removes a duplicated variable.
Patches 18 and 19 extract the am-specific and merge-specifc rebase
code into two new source files (as suggested by Hannes).
Patch 20 makes interactive rebase print the same message as
non-interactive rebase in case of conflict.
Patches 21 and 22 prepare for further refactoring by aligning
interactive and non-interactive rebase a bit more.
Patch 23 factors out part or all of the handling of --continue, --skip
and --abort from git-rebase--interactive to git-rebase.sh.
Patches 24-27 makes rebase remember more options passed on the command
line thoughout the rebase (past any conflicts).
Patches 28-31 remove some unnecessary code.
I have tried to separate pure refactoring from changes that make
functional changes, but there are still some functional changes hiding
in the "refactoring" patches. I have tried to point this out in the
commit message where applicable, but I'm sure I have missed a lot of
places.
/Martin
[1] http://thread.gmane.org/gmane.comp.version-control.git/160517
Martin von Zweigbergk (31):
rebase: clearer names for directory variables
rebase: refactor reading of state
rebase: read state outside loop
rebase: remove unused rebase state 'prev_head'
rebase: improve detection of rebase in progress
rebase: act on command line outside parsing loop
rebase: stricter check of standalone sub command
rebase: align variable names
rebase: align variable content
rebase: factor out command line option processing
rebase -i: remove now unnecessary directory checks
rebase: reorder validation steps
rebase: factor out reference parsing
rebase: factor out clean work tree check
rebase: factor out call to pre-rebase hook
rebase -i: support --stat
rebase: remove $branch as synonym for $orig_head
rebase: extract merge code to new source file
rebase: extract am code to new source file
rebase: show consistent conflict resolution hint
rebase -i: align variable names
rebase: make -v a tiny bit more verbose
rebase: factor out sub command handling
rebase: extract code for writing basic state
rebase: remember verbose option
rebase: remember strategy and strategy options
rebase -m: remember allow_rerere_autoupdate option
rebase -m: don't print exit code 2 when merge fails
git-rebase--am: remove unnecessary --3way option
rebase -i: don't read unused variable preserve_merges
rebase -i: remove unnecessary state rebase-root
.gitignore | 2 +
Makefile | 2 +
git-rebase--am.sh | 30 +++
git-rebase--interactive.sh | 589 ++++++++++++++------------------------------
git-rebase--merge.sh | 151 +++++++++++
git-rebase.sh | 477 ++++++++++++++---------------------
t/t3403-rebase-skip.sh | 5 +
t/t3407-rebase-abort.sh | 10 +
t/t3418-rebase-continue.sh | 55 ++++
9 files changed, 627 insertions(+), 694 deletions(-)
create mode 100644 git-rebase--am.sh
create mode 100644 git-rebase--merge.sh
--
1.7.3.2.864.gbbb96
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Detect early on if a rebase is in progress and what type of rebase it
is (interactive, merge-based or am-based). This prepares for further
refactoring where am-based rebase will be dispatched to
git-rebase--am.sh and merge-based rebase will be dispatched to
git-rebase--merge.sh.
The idea is to use the same variables whether the type of rebase was
detected from rebase-apply/ or rebase-merge/ directories or from the
command line options. This will make the code more readable and will
later also make it easier to dispatch to the type-specific scripts.
Also show a consistent error message independent of the type of rebase
that was in progress and remove the obsolete wording about being in
the middle of a 'patch application', since that (an existing
"$GIT_DIR"/rebase-apply/applying) aborts 'git rebase' at an earlier
stage.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Currently, the existence of rebase-merge/ is tested with 'test -d',
while the existence of rebase-apply/ is tested by creating the
directory and then deleting it again. Any good reason for this?
git-rebase.sh | 80 +++++++++++++++++++++++++++++---------------------------
1 files changed, 41 insertions(+), 39 deletions(-)
@@ -56,16 +56,19 @@ git_am_opt=rebase_root=force_rebase=allow_rerere_autoupdate=+# Non-empty if a rebase was in progress when 'git rebase' was invoked+in_progress=+# One of {am, merge, interactive}+type=+# One of {"$GIT_DIR"/rebase-apply, "$GIT_DIR"/rebase-merge}+state_dir= read_state(){-iftest-d"$merge_dir"+iftest"$type"=mergethen-state_dir="$merge_dir"-onto_name=$(cat"$merge_dir"/onto_name)&&-end=$(cat"$merge_dir"/end)&&-msgnum=$(cat"$merge_dir"/msgnum)-else-state_dir="$apply_dir"+onto_name=$(cat"$state_dir"/onto_name)&&+end=$(cat"$state_dir"/end)&&+msgnum=$(cat"$state_dir"/msgnum)fi&&head_name=$(cat"$state_dir"/head-name)&&onto=$(cat"$state_dir"/onto)&&
@@ -207,6 +210,23 @@ test -f "$apply_dir"/applying && is_interactive"$@"&&execgit-rebase--interactive"$@"+iftest-d"$apply_dir"+then+type=am+state_dir="$apply_dir"+eliftest-d"$merge_dir"+then+iftest-f"$merge_dir"/interactive+then+type=interactive+interactive_rebase=explicit+else+type=merge+fi+state_dir="$merge_dir"+fi+test-n"$type"&&in_progress=t+whiletest$#!=0docase"$1"in
@@ -217,8 +237,7 @@ doOK_TO_SKIP_PRE_REBASE=;;--continue)-test-d"$merge_dir"-o-d"$apply_dir"||-die"No rebase in progress?"+test-z"$in_progress"&&die"No rebase in progress?"gitupdate-index--ignore-submodules--refresh&&gitdiff-files--quiet--ignore-submodules||{
@@ -243,8 +262,7 @@ doexit;;--skip)-test-d"$merge_dir"-o-d"$apply_dir"||-die"No rebase in progress?"+test-z"$in_progress"&&die"No rebase in progress?"gitreset--hardHEAD||exit$?read_state
@@ -265,8 +283,7 @@ doexit;;--abort)-test-d"$merge_dir"-o-d"$apply_dir"||-die"No rebase in progress?"+test-z"$in_progress"&&die"No rebase in progress?"gitrerereclearread_state
@@ -374,37 +391,22 @@ dodonetest$#-gt2&&usage-iftest$#-eq0&&test-z"$rebase_root"+# Make sure no rebase is in progress+iftest-n"$in_progress"then-test-d"$merge_dir"-o-d"$apply_dir"||usage-test-d"$merge_dir"-o-f"$apply_dir"/rebasing&&-die'A rebase is in progress, try --continue, --skip or --abort.'-fi--# Make sure we do not have $apply_dir or $merge_dir-iftest-z"$do_merge"-then-ifmkdir"$apply_dir"2>/dev/null-then-rmdir"$apply_dir"-else-echo>&2'-ItseemsthatIcannotcreatearebase-applydirectory,and-Iwonderifyouareinthemiddleofpatchapplicationoranother-rebase.Ifthatisnotthecase,please-rm-fr'"$apply_dir"'+die'+Itseemsthatthereisalreadya'"${state_dir##*/}"'directory,and+Iwonderifyouareinthemiddleofanotherrebase.Ifthatisthe+case,pleasetry+gitrebase(--continue|--abort|--skip)+Ifthatisnotthecase,please+rm-fr'"$state_dir"' andrunmeagain.Iamstoppingincaseyoustillhavesomething valuablethere.'-exit1-fi-else-iftest-d"$merge_dir"-then-die"previous rebase directory $merge_dir still exists."\-'Try git rebase (--continue | --abort | --skip)'-fifi+test$#-eq0&&test-z"$rebase_root"&&usage+ require_clean_work_tree"rebase""Please commit or stash them."iftest-z"$rebase_root"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
The state stored in $GIT_DIR/rebase-merge/prev_head was introduced in
58634db (rebase: Allow merge strategies to be used when rebasing,
2006-06-21), but it was never used and should therefore be removed.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase.sh | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
@@ -75,7 +74,6 @@ read_state () {} continue_merge(){-test-n"$prev_head"||die"prev_head must be defined"test-d"$merge_dir"||die"$merge_dir directory does not exist"unmerged=$(gitls-files-u)
@@ -109,10 +107,6 @@ continue_merge () {test-z"$GIT_QUIET"&&GIT_PAGER=''gitlog--format=%s-1"$cmt"-prev_head=`gitrev-parseHEAD^0`-# save the resulting commit so we can read-tree on it later-echo"$prev_head">"$merge_dir/prev_head"-# onto the next patch:msgnum=$(($msgnum+1))echo"$msgnum">"$merge_dir/msgnum"
@@ -567,8 +561,6 @@ fi mkdir-p"$merge_dir"echo"$onto_name">"$merge_dir/onto_name"-prev_head=$orig_head-echo"$prev_head">"$merge_dir/prev_head"echo"$head_name">"$merge_dir/head-name"echo"$onto">"$merge_dir/onto"echo"$orig_head">"$merge_dir/orig-head"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
To later be able to use the command line processing in git-rebase.sh
for both interactive and non-interactive rebases, move anything that
is specific to non-interactive rebase outside of the parsing
loop. Keep only parsing and validation of command line options in the
loop.
Signed-off-by: Martin von Zweigbergk <redacted>
---
May want to view this patch with --ignore-all-space.
git-rebase--interactive.sh | 300 ++++++++++++++++++++++----------------------
git-rebase.sh | 126 ++++++++++---------
2 files changed, 217 insertions(+), 209 deletions(-)
@@ -866,152 +866,158 @@ first and then run 'git rebase --continue' again.";;--)shift-test-z"$REBASE_ROOT"-a$#-ge1-a$#-le2||-test!-z"$REBASE_ROOT"-a$#-le1||usage-test-d"$DOTEST"&&-die"Interactive rebase already started"--gitvarGIT_COMMITTER_IDENT>/dev/null||-die"You need to set your committer info first"--iftest-z"$REBASE_ROOT"-then-UPSTREAM_ARG="$1"-UPSTREAM=$(gitrev-parse--verify"$1")||die"Invalid base"-test-z"$ONTO"&&ONTO=$UPSTREAM-shift-else-UPSTREAM=-UPSTREAM_ARG=--root-test-z"$ONTO"&&-die"You must specify --onto when using --root"-fi-run_pre_rebase_hook"$UPSTREAM_ARG""$@"--comment_for_reflogstart--require_clean_work_tree"rebase""Please commit or stash them."--iftest!-z"$1"-then-outputgitcheckout"$1"||-die"Could not checkout $1"-fi+break+;;+esac+shift+done-HEAD=$(gitrev-parse--verifyHEAD)||die"No HEAD?"-mkdir"$DOTEST"||die"Could not create temporary $DOTEST"+test-z"$REBASE_ROOT"-a$#-ge1-a$#-le2||+test!-z"$REBASE_ROOT"-a$#-le1||usage+test-d"$DOTEST"&&+die"Interactive rebase already started"-:>"$DOTEST"/interactive||die"Could not mark as interactive"-gitsymbolic-refHEAD>"$DOTEST"/head-name2>/dev/null||-echo"detached HEAD">"$DOTEST"/head-name+gitvarGIT_COMMITTER_IDENT>/dev/null||+die"You need to set your committer info first"-echo$HEAD>"$DOTEST"/head-case"$REBASE_ROOT"in-'')-rm-f"$DOTEST"/rebase-root;;-*)-:>"$DOTEST"/rebase-root;;-esac-echo$ONTO>"$DOTEST"/onto-test-z"$STRATEGY"||echo"$STRATEGY">"$DOTEST"/strategy-testt="$VERBOSE"&&:>"$DOTEST"/verbose-iftestt="$PRESERVE_MERGES"-then-iftest-z"$REBASE_ROOT"-then-mkdir"$REWRITTEN"&&-forcin$(gitmerge-base--all$HEAD$UPSTREAM)-do-echo$ONTO>"$REWRITTEN"/$c||-die"Could not init rewritten commits"-done-else-mkdir"$REWRITTEN"&&-echo$ONTO>"$REWRITTEN"/root||-die"Could not init rewritten commits"-fi-# No cherry-pick because our first pass is to determine-# parents to rewrite and skipping dropped commits would-# prematurely end our probe-MERGES_OPTION=-first_after_upstream="$(gitrev-list--reverse--first-parent$UPSTREAM..$HEAD|head-n1)"-else-MERGES_OPTION="--no-merges --cherry-pick"-fi--SHORTHEAD=$(gitrev-parse--short$HEAD)-SHORTONTO=$(gitrev-parse--short$ONTO)-iftest-z"$REBASE_ROOT"-# this is now equivalent to ! -z "$UPSTREAM"-then-SHORTUPSTREAM=$(gitrev-parse--short$UPSTREAM)-REVISIONS=$UPSTREAM...$HEAD-SHORTREVISIONS=$SHORTUPSTREAM..$SHORTHEAD-else-REVISIONS=$ONTO...$HEAD-SHORTREVISIONS=$SHORTHEAD-fi-gitrev-list$MERGES_OPTION--pretty=oneline--abbrev-commit\---abbrev=7--reverse--left-right--topo-order\-$REVISIONS|\-sed-n"s/^>//p"|-whileread-rshortsha1rest+iftest-z"$REBASE_ROOT"+then+UPSTREAM_ARG="$1"+UPSTREAM=$(gitrev-parse--verify"$1")||die"Invalid base"+test-z"$ONTO"&&ONTO=$UPSTREAM+shift+else+UPSTREAM=+UPSTREAM_ARG=--root+test-z"$ONTO"&&+die"You must specify --onto when using --root"+fi+run_pre_rebase_hook"$UPSTREAM_ARG""$@"++comment_for_reflogstart++require_clean_work_tree"rebase""Please commit or stash them."++iftest!-z"$1"+then+outputgitcheckout"$1"||+die"Could not checkout $1"+fi++HEAD=$(gitrev-parse--verifyHEAD)||die"No HEAD?"+mkdir"$DOTEST"||die"Could not create temporary $DOTEST"++:>"$DOTEST"/interactive||die"Could not mark as interactive"+gitsymbolic-refHEAD>"$DOTEST"/head-name2>/dev/null||+echo"detached HEAD">"$DOTEST"/head-name++echo$HEAD>"$DOTEST"/head+case"$REBASE_ROOT"in+'')+rm-f"$DOTEST"/rebase-root;;+*)+:>"$DOTEST"/rebase-root;;+esac+echo$ONTO>"$DOTEST"/onto+test-z"$STRATEGY"||echo"$STRATEGY">"$DOTEST"/strategy+testt="$VERBOSE"&&:>"$DOTEST"/verbose+iftestt="$PRESERVE_MERGES"+then+iftest-z"$REBASE_ROOT"+then+mkdir"$REWRITTEN"&&+forcin$(gitmerge-base--all$HEAD$UPSTREAM)do-iftestt!="$PRESERVE_MERGES"-then-printf'%s\n'"pick $shortsha1$rest">>"$TODO"-else-sha1=$(gitrev-parse$shortsha1)-iftest-z"$REBASE_ROOT"-then-preserve=t-forpin$(gitrev-list--parents-1$sha1|cut-d' '-s-f2-)-do-iftest-f"$REWRITTEN"/$p-a\($p!=$ONTO-o$sha1=$first_after_upstream\)-then-preserve=f-fi-done-else-preserve=f-fi-iftestf="$preserve"-then-touch"$REWRITTEN"/$sha1-printf'%s\n'"pick $shortsha1$rest">>"$TODO"-fi-fi+echo$ONTO>"$REWRITTEN"/$c||+die"Could not init rewritten commits"done--# Watch for commits that been dropped by --cherry-pick-iftestt="$PRESERVE_MERGES"+else+mkdir"$REWRITTEN"&&+echo$ONTO>"$REWRITTEN"/root||+die"Could not init rewritten commits"+fi+# No cherry-pick because our first pass is to determine+# parents to rewrite and skipping dropped commits would+# prematurely end our probe+MERGES_OPTION=+first_after_upstream="$(gitrev-list--reverse--first-parent$UPSTREAM..$HEAD|head-n1)"+else+MERGES_OPTION="--no-merges --cherry-pick"+fi++SHORTHEAD=$(gitrev-parse--short$HEAD)+SHORTONTO=$(gitrev-parse--short$ONTO)+iftest-z"$REBASE_ROOT"+# this is now equivalent to ! -z "$UPSTREAM"+then+SHORTUPSTREAM=$(gitrev-parse--short$UPSTREAM)+REVISIONS=$UPSTREAM...$HEAD+SHORTREVISIONS=$SHORTUPSTREAM..$SHORTHEAD+else+REVISIONS=$ONTO...$HEAD+SHORTREVISIONS=$SHORTHEAD+fi+gitrev-list$MERGES_OPTION--pretty=oneline--abbrev-commit\+--abbrev=7--reverse--left-right--topo-order\+$REVISIONS|\+sed-n"s/^>//p"|+whileread-rshortsha1rest+do+iftestt!="$PRESERVE_MERGES"+then+printf'%s\n'"pick $shortsha1$rest">>"$TODO"+else+sha1=$(gitrev-parse$shortsha1)+iftest-z"$REBASE_ROOT"then-mkdir"$DROPPED"-# Save all non-cherry-picked changes-gitrev-list$REVISIONS--left-right--cherry-pick|\-sed-n"s/^>//p">"$DOTEST"/not-cherry-picks-# Now all commits and note which ones are missing in-# not-cherry-picks and hence being dropped-gitrev-list$REVISIONS|-whilereadrev+preserve=t+forpin$(gitrev-list--parents-1$sha1|cut-d' '-s-f2-)do-iftest-f"$REWRITTEN"/$rev-a"$(sane_grep"$rev""$DOTEST"/not-cherry-picks)"=""+iftest-f"$REWRITTEN"/$p-a\($p!=$ONTO-o$sha1=$first_after_upstream\)then-# Use -f2 because if rev-list is telling us this commit is-# not worthwhile, we don't want to track its multiple heads,-# just the history of its first-parent for others that will-# be rebasing on top of it-gitrev-list--parents-1$rev|cut-d' '-s-f2>"$DROPPED"/$rev-short=$(gitrev-list-1--abbrev-commit--abbrev=7$rev)-sane_grep-v"^[a-z][a-z]* $short"<"$TODO">"${TODO}2";mv"${TODO}2""$TODO"-rm"$REWRITTEN"/$rev+preserve=ffidone+else+preserve=f+fi+iftestf="$preserve"+then+touch"$REWRITTEN"/$sha1+printf'%s\n'"pick $shortsha1$rest">>"$TODO"fi+fi+done-test-s"$TODO"||echonoop>>"$TODO"-test-n"$AUTOSQUASH"&&rearrange_squash"$TODO"-cat>>"$TODO"<<EOF+# Watch for commits that been dropped by --cherry-pick+iftestt="$PRESERVE_MERGES"+then+mkdir"$DROPPED"+# Save all non-cherry-picked changes+gitrev-list$REVISIONS--left-right--cherry-pick|\+sed-n"s/^>//p">"$DOTEST"/not-cherry-picks+# Now all commits and note which ones are missing in+# not-cherry-picks and hence being dropped+gitrev-list$REVISIONS|+whilereadrev+do+iftest-f"$REWRITTEN"/$rev-a"$(sane_grep"$rev""$DOTEST"/not-cherry-picks)"=""+then+# Use -f2 because if rev-list is telling us this commit is+# not worthwhile, we don't want to track its multiple heads,+# just the history of its first-parent for others that will+# be rebasing on top of it+gitrev-list--parents-1$rev|cut-d' '-s-f2>"$DROPPED"/$rev+short=$(gitrev-list-1--abbrev-commit--abbrev=7$rev)+sane_grep-v"^[a-z][a-z]* $short"<"$TODO">"${TODO}2";mv"${TODO}2""$TODO"+rm"$REWRITTEN"/$rev+fi+done+fi++test-s"$TODO"||echonoop>>"$TODO"+test-n"$AUTOSQUASH"&&rearrange_squash"$TODO"+cat>>"$TODO"<<EOF# Rebase $SHORTREVISIONS onto $SHORTONTO#
@@ -1028,22 +1034,18 @@ first and then run 'git rebase --continue' again."# EOF-has_action"$TODO"||-die_abort"Nothing to do"+has_action"$TODO"||+die_abort"Nothing to do"-cp"$TODO""$TODO".backup-git_editor"$TODO"||-die_abort"Could not execute editor"+cp"$TODO""$TODO".backup+git_editor"$TODO"||+die_abort"Could not execute editor"-has_action"$TODO"||-die_abort"Nothing to do"+has_action"$TODO"||+die_abort"Nothing to do"-test-d"$REWRITTEN"||test-n"$NEVER_FF"||skip_unnecessary_picks+test-d"$REWRITTEN"||test-n"$NEVER_FF"||skip_unnecessary_picks-outputgitcheckout$ONTO||die_abort"could not detach HEAD"-gitupdate-refORIG_HEAD$HEAD-do_rest-;;-esac-shift-done+outputgitcheckout$ONTO||die_abort"could not detach HEAD"+gitupdate-refORIG_HEAD$HEAD+do_rest
@@ -62,6 +62,8 @@ in_progress=type=# One of {"$GIT_DIR"/rebase-apply, "$GIT_DIR"/rebase-merge}state_dir=+# One of {'', continue, skip, abort}, as parsed from command line+action= read_state(){iftest"$type"=merge
@@ -236,66 +238,10 @@ do--verify)OK_TO_SKIP_PRE_REBASE=;;---continue)-test-z"$in_progress"&&die"No rebase in progress?"--gitupdate-index--ignore-submodules--refresh&&-gitdiff-files--quiet--ignore-submodules||{-echo"You must edit all merge conflicts and then"-echo"mark them as resolved using git add"-exit1-}-read_state-iftest-d"$merge_dir"-then-continue_merge-whiletest"$msgnum"-le"$end"-do-call_merge"$msgnum"-continue_merge-done-finish_rb_merge-exit-fi-gitam--resolved--3way--resolvemsg="$RESOLVEMSG"&&-move_to_original_branch-exit-;;---skip)-test-z"$in_progress"&&die"No rebase in progress?"--gitreset--hardHEAD||exit$?-read_state-iftest-d"$merge_dir"-then-gitrerereclear-msgnum=$(($msgnum+1))-whiletest"$msgnum"-le"$end"-do-call_merge"$msgnum"-continue_merge-done-finish_rb_merge-exit-fi-gitam-3--skip--resolvemsg="$RESOLVEMSG"&&-move_to_original_branch-exit-;;---abort)-test-z"$in_progress"&&die"No rebase in progress?"--gitrerereclear-read_state-case"$head_name"in-refs/*)-gitsymbolic-refHEAD$head_name||-die"Could not move back to $head_name"-;;-esac-gitreset--hard$orig_head-rm-r"$state_dir"-exit+--continue|--skip|--abort)+action=${1##--}+shift+break;;--onto)test2-le"$#"||usage
@@ -391,6 +337,66 @@ dodonetest$#-gt2&&usage+test-n"$action"&&test-z"$in_progress"&&die"No rebase in progress?"++case"$action"in+continue)+gitupdate-index--ignore-submodules--refresh&&+gitdiff-files--quiet--ignore-submodules||{+echo"You must edit all merge conflicts and then"+echo"mark them as resolved using git add"+exit1+}+read_state+iftest-d"$merge_dir"+then+continue_merge+whiletest"$msgnum"-le"$end"+do+call_merge"$msgnum"+continue_merge+done+finish_rb_merge+exit+fi+gitam--resolved--3way--resolvemsg="$RESOLVEMSG"&&+move_to_original_branch+exit+;;+skip)+gitreset--hardHEAD||exit$?+read_state+iftest-d"$merge_dir"+then+gitrerereclear+msgnum=$(($msgnum+1))+whiletest"$msgnum"-le"$end"+do+call_merge"$msgnum"+continue_merge+done+finish_rb_merge+exit+fi+gitam-3--skip--resolvemsg="$RESOLVEMSG"&&+move_to_original_branch+exit+;;+abort)+gitrerereclear+read_state+case"$head_name"in+refs/*)+gitsymbolic-refHEAD$head_name||+die"Could not move back to $head_name"+;;+esac+gitreset--hard$orig_head+rm-r"$state_dir"+exit+;;+esac+# Make sure no rebase is in progressiftest-n"$in_progress"then
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Make sure to interpret variables with the same name in the same way in
git-rebase.sh and git-rebase--interactive.sh. This will make it easier
to factor out code from git-rebase.sh to git-rebase--interactive and
export the variables.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 16 +++++++++++-----
git-rebase.sh | 4 +++-
2 files changed, 14 insertions(+), 6 deletions(-)
@@ -339,7 +339,8 @@ pick_one_preserving_merges () {# No point in merging the first parent, that's HEADnew_parents=${new_parents# $first_parent}if!do_with_authoroutput\-gitmerge$strategy-m"$msg"$new_parents+gitmerge${strategy:+-s $strategy}-m"$msg"\+$new_parentsthenprintf"%s\n""$msg">"$GIT_DIR"/MERGE_MSGdie_with_patch$sha1"Error redoing merge $sha1"
@@ -827,11 +828,11 @@ first and then run 'git rebase --continue' again."-s)case"$#,$1"in*,*=*)-strategy="-s "$(expr"z$1":'z-[^=]*=\(.*\)');;+strategy=$(expr"z$1":'z-[^=]*=\(.*\)');;1,*)usage;;*)-strategy="-s $2"+strategy="$2"shift;;esac;;
@@ -860,9 +861,9 @@ first and then run 'git rebase --continue' again."autosquash=;;--onto)+test2-le"$#"||usage+onto="$2"shift-onto=$(parse_onto"$1")||-die"Does not point to a valid commit: $1";;--)shift
@@ -872,6 +873,11 @@ first and then run 'git rebase --continue' again."shiftdone+iftest-n"$onto"+then+onto=$(parse_onto"$onto")||die"Does not point to a valid commit: $1"+fi+test-z"$rebase_root"-a$#-ge1-a$#-le2||test!-z"$rebase_root"-a$#-le1||usagetest-d"$DOTEST"&&
@@ -43,7 +43,7 @@ If you would prefer to skip this patch, instead run \"git rebase --skip\". Torestoretheoriginalbranchandstoprebasingrun\"gitrebase--abort\"."unsetonto-strategy=recursive+strategy=strategy_opts=do_merge=merge_dir="$GIT_DIR"/rebase-merge
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Reorder validation steps in preparation for the validation to be factored
out from git-rebase--interactive.sh into git-rebase.sh.
The main functional difference is that the pre-rebase hook will no longer
be run if the work tree is dirty.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 4 ++--
git-rebase.sh | 10 +++++-----
2 files changed, 7 insertions(+), 7 deletions(-)
@@ -792,12 +792,12 @@ elsetest-z"$onto"&&die"You must specify --onto when using --root"fi+require_clean_work_tree"rebase""Please commit or stash them."+ run_pre_rebase_hook"$upstream_arg""$@" comment_for_reflogstart-require_clean_work_tree"rebase""Please commit or stash them."-iftest!-z"$1"thenoutputgitcheckout"$1"||
@@ -435,8 +435,6 @@ fitest"$type"=interactive&&run_interactive_rebase"$@"-require_clean_work_tree"rebase""Please commit or stash them."-iftest-z"$rebase_root"then# The upstream head must be given. Make sure it is valid.
@@ -478,9 +476,6 @@ case "$onto_name" in;;esac-# If a hook exists, give it a chance to interrupt-run_pre_rebase_hook"$upstream_arg""$@"-# If the branch to rebase is given, that is the branch we will rebase# $branch_name -- branch being rebased, or HEAD (already detached)# $orig_head -- commit object name of tip of the branch before rebasing
@@ -518,6 +513,8 @@ case "$#" inesacorig_head=$branch+require_clean_work_tree"rebase""Please commit or stash them."+# Now we are rebasing commits $upstream..$branch (or with --root,# everything leading up to $branch) on top of $onto
@@ -539,6 +536,9 @@ thenfifi+# If a hook exists, give it a chance to interrupt+run_pre_rebase_hook"$upstream_arg""$@"+# Detach HEAD and reset the tree say"First, rewinding head to replay your work on top of it..." gitcheckout-q"$onto^0"||die"could not detach HEAD"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Use the same names for variables that git-rebase--interactive.sh will
soon inherit from git-rebase.sh.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 138 ++++++++++++++++++++++----------------------
git-rebase.sh | 8 +-
2 files changed, 73 insertions(+), 73 deletions(-)
@@ -77,7 +77,7 @@ FIXUP_MSG="$DOTEST"/message-fixup# $REWRITTEN is the name of a directory containing files for each# commit that is reachable by at least one merge base of $HEAD and-# $UPSTREAM. They are not necessarily rewritten, but their children+# $upstream. They are not necessarily rewritten, but their children# might be. This ensures that commits on merged, but otherwise# unrelated side branches are left alone. (Think "X" in the man page's# example.)
@@ -339,7 +339,7 @@ pick_one_preserving_merges () {# No point in merging the first parent, that's HEADnew_parents=${new_parents# $first_parent}if!do_with_authoroutput\-gitmerge$STRATEGY-m"$msg"$new_parents+gitmerge$strategy-m"$msg"$new_parentsthenprintf"%s\n""$msg">"$GIT_DIR"/MERGE_MSGdie_with_patch$sha1"Error redoing merge $sha1"
@@ -618,11 +618,11 @@ skip_unnecessary_picks () {# fd=3 means we skip the commandcase"$fd,$command"in3,pick|3,p)-# pick a commit whose parent is current $ONTO -> skip+# pick a commit whose parent is current $onto -> skipsha1=${rest%% *}case"$(gitrev-parse--verify--quiet"$sha1"^)"in-"$ONTO"*)-ONTO=$sha1+"$onto"*)+onto=$sha1;;*)fd=1
@@ -650,17 +650,17 @@ skip_unnecessary_picks () {# check if no other options are set is_standalone(){test$#-eq2-a"$2"='--'&&-test-z"$ONTO"&&-test-z"$PRESERVE_MERGES"&&-test-z"$STRATEGY"&&-test-z"$VERBOSE"+test-z"$onto"&&+test-z"$preserve_merges"&&+test-z"$strategy"&&+test-z"$verbose"} get_saved_options(){-test-d"$REWRITTEN"&&PRESERVE_MERGES=t-test-f"$DOTEST"/strategy&&STRATEGY="$(cat"$DOTEST"/strategy)"-test-f"$DOTEST"/verbose&&VERBOSE=t-test-f"$DOTEST"/rebase-root&&REBASE_ROOT=t+test-d"$REWRITTEN"&&preserve_merges=t+test-f"$DOTEST"/strategy&&strategy="$(cat"$DOTEST"/strategy)"+test-f"$DOTEST"/verbose&&verbose=t+test-f"$DOTEST"/rebase-root&&rebase_root=t}# Rearrange the todo list that has both "pick sha1 msg" and
@@ -827,11 +827,11 @@ first and then run 'git rebase --continue' again."-s)case"$#,$1"in*,*=*)-STRATEGY="-s "$(expr"z$1":'z-[^=]*=\(.*\)');;+strategy="-s "$(expr"z$1":'z-[^=]*=\(.*\)');;1,*)usage;;*)-STRATEGY="-s $2"+strategy="-s $2"shift;;esac;;
@@ -839,29 +839,29 @@ first and then run 'git rebase --continue' again."# we use merge anyway;;-v)-VERBOSE=t+verbose=t;;-p)-PRESERVE_MERGES=t+preserve_merges=t;;-i)# yeah, we know;;--no-ff)-NEVER_FF=t+force_rebase=t;;--root)-REBASE_ROOT=t+rebase_root=t;;--autosquash)-AUTOSQUASH=t+autosquash=t;;--no-autosquash)-AUTOSQUASH=+autosquash=;;--onto)shift-ONTO=$(parse_onto"$1")||+onto=$(parse_onto"$1")||die"Does not point to a valid commit: $1";;--)
@@ -872,27 +872,27 @@ first and then run 'git rebase --continue' again."shiftdone-test-z"$REBASE_ROOT"-a$#-ge1-a$#-le2||-test!-z"$REBASE_ROOT"-a$#-le1||usage+test-z"$rebase_root"-a$#-ge1-a$#-le2||+test!-z"$rebase_root"-a$#-le1||usagetest-d"$DOTEST"&&die"Interactive rebase already started" gitvarGIT_COMMITTER_IDENT>/dev/null||die"You need to set your committer info first"-iftest-z"$REBASE_ROOT"+iftest-z"$rebase_root"then-UPSTREAM_ARG="$1"-UPSTREAM=$(gitrev-parse--verify"$1")||die"Invalid base"-test-z"$ONTO"&&ONTO=$UPSTREAM+upstream_arg="$1"+upstream=$(gitrev-parse--verify"$1")||die"Invalid base"+test-z"$onto"&&onto=$upstreamshiftelse-UPSTREAM=-UPSTREAM_ARG=--root-test-z"$ONTO"&&-die"You must specify --onto when using --root"+upstream=+upstream_arg=--root+test-z"$onto"&&+die"You must specify --onto when using --root"fi-run_pre_rebase_hook"$UPSTREAM_ARG""$@"+run_pre_rebase_hook"$upstream_arg""$@" comment_for_reflogstart
@@ -912,49 +912,49 @@ git symbolic-ref HEAD > "$DOTEST"/head-name 2> /dev/null ||echo"detached HEAD">"$DOTEST"/head-nameecho$HEAD>"$DOTEST"/head-case"$REBASE_ROOT"in+case"$rebase_root"in'')rm-f"$DOTEST"/rebase-root;; *):>"$DOTEST"/rebase-root;;esac-echo$ONTO>"$DOTEST"/onto-test-z"$STRATEGY"||echo"$STRATEGY">"$DOTEST"/strategy-testt="$VERBOSE"&&:>"$DOTEST"/verbose-iftestt="$PRESERVE_MERGES"+echo$onto>"$DOTEST"/onto+test-z"$strategy"||echo"$strategy">"$DOTEST"/strategy+testt="$verbose"&&:>"$DOTEST"/verbose+iftestt="$preserve_merges"then-iftest-z"$REBASE_ROOT"+iftest-z"$rebase_root"thenmkdir"$REWRITTEN"&&-forcin$(gitmerge-base--all$HEAD$UPSTREAM)+forcin$(gitmerge-base--all$HEAD$upstream)do-echo$ONTO>"$REWRITTEN"/$c||+echo$onto>"$REWRITTEN"/$c||die"Could not init rewritten commits"doneelsemkdir"$REWRITTEN"&&-echo$ONTO>"$REWRITTEN"/root||+echo$onto>"$REWRITTEN"/root||die"Could not init rewritten commits"fi# No cherry-pick because our first pass is to determine# parents to rewrite and skipping dropped commits would# prematurely end our probeMERGES_OPTION=-first_after_upstream="$(gitrev-list--reverse--first-parent$UPSTREAM..$HEAD|head-n1)"+first_after_upstream="$(gitrev-list--reverse--first-parent$upstream..$HEAD|head-n1)"elseMERGES_OPTION="--no-merges --cherry-pick"fiSHORTHEAD=$(gitrev-parse--short$HEAD)-SHORTONTO=$(gitrev-parse--short$ONTO)-iftest-z"$REBASE_ROOT"-# this is now equivalent to ! -z "$UPSTREAM"+SHORTONTO=$(gitrev-parse--short$onto)+iftest-z"$rebase_root"+# this is now equivalent to ! -z "$upstream"then-SHORTUPSTREAM=$(gitrev-parse--short$UPSTREAM)-REVISIONS=$UPSTREAM...$HEAD+SHORTUPSTREAM=$(gitrev-parse--short$upstream)+REVISIONS=$upstream...$HEADSHORTREVISIONS=$SHORTUPSTREAM..$SHORTHEADelse-REVISIONS=$ONTO...$HEAD+REVISIONS=$onto...$HEADSHORTREVISIONS=$SHORTHEADfi gitrev-list$MERGES_OPTION--pretty=oneline--abbrev-commit\
@@ -990,7 +990,7 @@ dodone# Watch for commits that been dropped by --cherry-pick-iftestt="$PRESERVE_MERGES"+iftestt="$preserve_merges"thenmkdir"$DROPPED"# Save all non-cherry-picked changes
@@ -1016,7 +1016,7 @@ thenfitest-s"$TODO"||echonoop>>"$TODO"-test-n"$AUTOSQUASH"&&rearrange_squash"$TODO"+test-n"$autosquash"&&rearrange_squash"$TODO" cat>>"$TODO"<<EOF# Rebase $SHORTREVISIONS onto $SHORTONTO
@@ -1044,8 +1044,8 @@ git_editor "$TODO" || has_action"$TODO"||die_abort"Nothing to do"-test-d"$REWRITTEN"||test-n"$NEVER_FF"||skip_unnecessary_picks+test-d"$REWRITTEN"||test-n"$force_rebase"||skip_unnecessary_picks-outputgitcheckout$ONTO||die_abort"could not detach HEAD"+outputgitcheckout$onto||die_abort"could not detach HEAD" gitupdate-refORIG_HEAD$HEAD do_rest
@@ -42,7 +42,7 @@ When you have resolved this problem run \"git rebase --continue\". Ifyouwouldprefertoskipthispatch,insteadrun\"gitrebase--skip\". Torestoretheoriginalbranchandstoprebasingrun\"gitrebase--abort\"."-unsetnewbase+unsetontostrategy=recursivestrategy_opts=do_merge=
@@ -425,7 +425,7 @@ thenunsetroot_flagupstream_arg="$upstream_name"else-test-z"$newbase"&&die"--root must be used with --onto"+test-z"$onto"&&die"--root must be used with --onto"unsetupstream_nameunsetupstreamroot_flag="--root"
@@ -433,7 +433,7 @@ elsefi# Make sure the branch to rebase onto is valid.-onto_name=${newbase-"$upstream_name"}+onto_name=${onto-"$upstream_name"}case"$onto_name"in *...*)ifleft=${onto_name%...*}right=${onto_name#*...}&&
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Factor out the command line processing in git-rebase--interactive.sh
to git-rebase.sh. Store the options in variables in git-rebase.sh and
export them before calling git-rebase--interactive.sh.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Since this removes the command line processing from
git-rebase--interactive.sh, it completely changes its command line
interface. Since it is not listed as even a plumbing command, I hope
this is fine.
git-rebase--interactive.sh | 224 ++++++++++++--------------------------------
git-rebase.sh | 60 ++++++++----
2 files changed, 102 insertions(+), 182 deletions(-)
@@ -10,31 +10,7 @@# The original idea comes from Eric W. Biederman, in# http://article.gmane.org/gmane.comp.version-control.git/22407-OPTIONS_KEEPDASHDASH=-OPTIONS_SPEC="\-git-rebase[-i][options][--]<upstream>[<branch>]-git-rebase[-i](--continue|--abort|--skip)----Availableoptionsare-v,verbosedisplayadiffstatofwhatchangedupstream-onto=rebaseontogivenbranchinsteadofupstream-p,preserve-mergestrytorecreatemergesinsteadofignoringthem-s,strategy=usethegivenmergestrategy-no-ffcherry-pickallcommits,evenifunchanged-m,mergealwaysused(no-op)-i,interactivealwaysused(no-op)-Actions:-continuecontinuerebasingprocess-abortabortrebasingprocessandrestoreoriginalbranch-skipskipcurrentpatchandcontinuerebasingprocess-no-verifyoverridepre-rebasehookfromstoppingtheoperation-verifyallowpre-rebasehooktorun-rootrebaseallreachablecommmitsuptotheroot(s)-autosquashmovecommitsthatbeginwithsquash!/fixup!under-i-"- .git-sh-setup-require_work_treeDOTEST="$GIT_DIR/rebase-merge"
@@ -648,15 +614,6 @@ skip_unnecessary_picks () {die"Could not skip unnecessary pick commands"}-# check if no other options are set-is_standalone(){-test$#-eq2-a"$2"='--'&&-test-z"$onto"&&-test-z"$preserve_merges"&&-test-z"$strategy"&&-test-z"$verbose"-}- get_saved_options(){test-d"$REWRITTEN"&&preserve_merges=ttest-f"$DOTEST"/strategy&&strategy="$(cat"$DOTEST"/strategy)"
@@ -744,134 +701,77 @@ parse_onto () {gitrev-parse--verify"$1^0"}-whiletest$#!=0-do-case"$1"in---no-verify)-OK_TO_SKIP_PRE_REBASE=yes-;;---verify)-OK_TO_SKIP_PRE_REBASE=-;;---continue)-is_standalone"$@"||usage-get_saved_options-comment_for_reflogcontinue--test-d"$DOTEST"||die"No interactive rebase running"--# Sanity check-gitrev-parse--verifyHEAD>/dev/null||-die"Cannot read HEAD"-gitupdate-index--ignore-submodules--refresh&&-gitdiff-files--quiet--ignore-submodules||-die"Working tree is dirty"--# do we have anything to commit?-ifgitdiff-index--cached--quiet--ignore-submodulesHEAD--+case"$action"in+continue)+get_saved_options+comment_for_reflogcontinue++test-d"$DOTEST"||die"No interactive rebase running"++# Sanity check+gitrev-parse--verifyHEAD>/dev/null||+die"Cannot read HEAD"+gitupdate-index--ignore-submodules--refresh&&+gitdiff-files--quiet--ignore-submodules||+die"Working tree is dirty"++# do we have anything to commit?+ifgitdiff-index--cached--quiet--ignore-submodulesHEAD--+then+:Nothingtocommit--skipthis+else+."$AUTHOR_SCRIPT"||+die"Cannot find the author identity"+amend=+iftest-f"$AMEND"then-:Nothingtocommit--skipthis-else-."$AUTHOR_SCRIPT"||-die"Cannot find the author identity"-amend=-iftest-f"$AMEND"-then-amend=$(gitrev-parse--verifyHEAD)-test"$amend"=$(cat"$AMEND")||-die"\+amend=$(gitrev-parse--verifyHEAD)+test"$amend"=$(cat"$AMEND")||+die"\ Youhaveuncommittedchangesinyourworkingtree.Please,committhem firstandthenrun'git rebase --continue'again."-gitreset--softHEAD^||-die"Cannot rewind the HEAD"-fi-do_with_authorgitcommit--no-verify-F"$MSG"-e||{-test-n"$amend"&&gitreset--soft$amend-die"Could not commit staged changes."-}+gitreset--softHEAD^||+die"Cannot rewind the HEAD"fi+do_with_authorgitcommit--no-verify-F"$MSG"-e||{+test-n"$amend"&&gitreset--soft$amend+die"Could not commit staged changes."+}+fi-record_in_rewritten"$(cat"$DOTEST"/stopped-sha)"+record_in_rewritten"$(cat"$DOTEST"/stopped-sha)"-require_clean_work_tree"rebase"-do_rest-;;---abort)-is_standalone"$@"||usage-get_saved_options-comment_for_reflogabort--gitrerereclear-test-d"$DOTEST"||die"No interactive rebase running"--HEADNAME=$(cat"$DOTEST"/head-name)-HEAD=$(cat"$DOTEST"/head)-case$HEADNAMEin-refs/*)-gitsymbolic-refHEAD$HEADNAME-;;-esac&&-outputgitreset--hard$HEAD&&-rm-rf"$DOTEST"-exit-;;---skip)-is_standalone"$@"||usage-get_saved_options-comment_for_reflogskip+require_clean_work_tree"rebase"+do_rest+;;+abort)+get_saved_options+comment_for_reflogabort-gitrerereclear-test-d"$DOTEST"||die"No interactive rebase running"+gitrerereclear+test-d"$DOTEST"||die"No interactive rebase running"-outputgitreset--hard&&do_rest-;;--s)-case"$#,$1"in-*,*=*)-strategy=$(expr"z$1":'z-[^=]*=\(.*\)');;-1,*)-usage;;-*)-strategy="$2"-shift;;-esac-;;--m)-# we use merge anyway-;;--v)-verbose=t-;;--p)-preserve_merges=t-;;--i)-# yeah, we know-;;---no-ff)-force_rebase=t-;;---root)-rebase_root=t-;;---autosquash)-autosquash=t-;;---no-autosquash)-autosquash=-;;---onto)-test2-le"$#"||usage-onto="$2"-shift-;;---)-shift-break+HEADNAME=$(cat"$DOTEST"/head-name)+HEAD=$(cat"$DOTEST"/head)+case$HEADNAMEin+refs/*)+gitsymbolic-refHEAD$HEADNAME;;-esac-shift-done+esac&&+outputgitreset--hard$HEAD&&+rm-rf"$DOTEST"+exit+;;+skip)+get_saved_options+comment_for_reflogskip++gitrerereclear+test-d"$DOTEST"||die"No interactive rebase running"++outputgitreset--hard&&do_rest+;;+esaciftest-n"$onto"then
@@ -64,6 +64,9 @@ type=state_dir=# One of {'', continue, skip, abort}, as parsed from command lineaction=+preserve_merges=+autosquash=+test"$(gitconfig--boolrebase.autosquash)"="true"&&autosquash=t read_state(){iftest"$type"=merge
@@ -211,8 +201,6 @@ run_pre_rebase_hook () {test-f"$apply_dir"/applying&&die'It looks like git-am is in progress. Cannot rebase.'-is_interactive"$@"&&execgit-rebase--interactive"$@"-iftest-d"$apply_dir"thentype=am
@@ -339,7 +340,11 @@ dodonetest$#-gt2&&usage-test-n"$action"&&test-z"$in_progress"&&die"No rebase in progress?"+iftest-n"$action"+then+test-z"$in_progress"&&die"No rebase in progress?"+test"$type"=interactive&&run_interactive_rebase+ficase"$action"incontinue)
@@ -415,6 +420,21 @@ fitest$#-eq0&&test-z"$rebase_root"&&usage+iftest-n"$interactive_rebase"+then+type=interactive+state_dir="$merge_dir"+eliftest-n"$do_merge"+then+type=merge+state_dir="$merge_dir"+else+type=am+state_dir="$apply_dir"+fi++test"$type"=interactive&&run_interactive_rebase"$@"+ require_clean_work_tree"rebase""Please commit or stash them."iftest-z"$rebase_root"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Remove the call to the pre-rebase hook from
git-rebase--interactive.sh and rely on the call in
git-rebase.sh.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 14 --------------
git-rebase.sh | 15 ++++++++-------
2 files changed, 8 insertions(+), 21 deletions(-)
@@ -753,8 +741,6 @@ esac gitvarGIT_COMMITTER_IDENT>/dev/null||die"You need to set your committer info first"-run_pre_rebase_hook"$upstream_arg""$@"- comment_for_reflogstartiftest!-z"$switch_to"
@@ -515,15 +514,15 @@ orig_head=$branch require_clean_work_tree"rebase""Please commit or stash them."-test"$type"=interactive&&run_interactive_rebase"$@"-# Now we are rebasing commits $upstream..$branch (or with --root,# everything leading up to $branch) on top of $onto# Check if we are already based on $onto with linear history,-# but this should be done only when upstream and onto are the same.+# but this should be done only when upstream and onto are the same+# and if this is not an interactive rebase.mb=$(gitmerge-base"$onto""$branch")-iftest"$upstream"="$onto"&&test"$mb"="$onto"&&+iftest"$type"!=interactive&&test"$upstream"="$onto"&&+test"$mb"="$onto"&&# linear history?!(gitrev-list--parents"$onto".."$branch"|sane_grep" .* ")>/dev/nullthen
@@ -541,6 +540,8 @@ fi# If a hook exists, give it a chance to interrupt run_pre_rebase_hook"$upstream_arg""$@"+test"$type"=interactive&&run_interactive_rebase+# Detach HEAD and reset the tree say"First, rewinding head to replay your work on top of it..." gitcheckout-q"$onto^0"||die"could not detach HEAD"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Remove directory checks from git-rebase--interactive.sh that are done in
git-rebase.sh.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Squash with previous?
git-rebase--interactive.sh | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
@@ -749,7 +747,6 @@ abort)comment_for_reflogabortgitrerereclear-test-d"$DOTEST"||die"No interactive rebase running"HEADNAME=$(cat"$DOTEST"/head-name)HEAD=$(cat"$DOTEST"/head)
@@ -767,7 +764,6 @@ skip)comment_for_reflogskipgitrerereclear-test-d"$DOTEST"||die"No interactive rebase running"outputgitreset--hard&&do_rest;;
@@ -780,8 +776,6 @@ fitest-z"$rebase_root"-a$#-ge1-a$#-le2||test!-z"$rebase_root"-a$#-le1||usage-test-d"$DOTEST"&&-die"Interactive rebase already started" gitvarGIT_COMMITTER_IDENT>/dev/null||die"You need to set your committer info first"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Move up the code that displays the diffstat if '--stat' is passed, so
that it will be executed before calling git-rebase--interactive.sh.
A side effect is that the diffstat is now displayed before "First,
rewinding head to replay your work on top of it...".
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase.sh | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
@@ -540,13 +540,6 @@ fi# If a hook exists, give it a chance to interrupt run_pre_rebase_hook"$upstream_arg""$@"-test"$type"=interactive&&run_interactive_rebase--# Detach HEAD and reset the tree-say"First, rewinding head to replay your work on top of it..."-gitcheckout-q"$onto^0"||die"could not detach HEAD"-gitupdate-refORIG_HEAD$branch-iftest-n"$diffstat"theniftest-n"$verbose"
@@ -557,6 +550,13 @@ thenGIT_PAGER=''gitdiff--stat--summary"$mb""$onto"fi+test"$type"=interactive&&run_interactive_rebase++# Detach HEAD and reset the tree+say"First, rewinding head to replay your work on top of it..."+gitcheckout-q"$onto^0"||die"could not detach HEAD"+gitupdate-refORIG_HEAD$branch+# If the $onto is a proper descendant of the tip of the branch, then# we just fast-forwarded.iftest"$mb"="$branch"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Remove the check for clean work tree from git-rebase--interactive.sh and
rely on the check in git-rebase.sh.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 2 --
git-rebase.sh | 4 ++--
2 files changed, 2 insertions(+), 4 deletions(-)
@@ -753,8 +753,6 @@ esac gitvarGIT_COMMITTER_IDENT>/dev/null||die"You need to set your committer info first"-require_clean_work_tree"rebase""Please commit or stash them."- run_pre_rebase_hook"$upstream_arg""$@" comment_for_reflogstart
@@ -513,10 +513,10 @@ case "$#" inesacorig_head=$branch-test"$type"=interactive&&run_interactive_rebase"$@"- require_clean_work_tree"rebase""Please commit or stash them."+test"$type"=interactive&&run_interactive_rebase"$@"+# Now we are rebasing commits $upstream..$branch (or with --root,# everything leading up to $branch) on top of $onto
@@ -0,0 +1,34 @@+#!/bin/sh+#+# Copyright (c) 2010 Junio C Hamano.+#++.git-sh-setup++case"$action"in+continue)+gitam--resolved--3way--resolvemsg="$RESOLVEMSG"&&+move_to_original_branch+exit+;;+skip)+gitam--skip-3--resolvemsg="$RESOLVEMSG"&&+move_to_original_branch+exit+;;+esac++test-n"$rebase_root"&&root_flag=--root++gitformat-patch-k--stdout--full-index--ignore-if-in-upstream\+--src-prefix=a/--dst-prefix=b/\+--no-renames$root_flag"$revisions"|+gitam$git_am_opt--rebasing--resolvemsg="$RESOLVEMSG"&&+move_to_original_branch+ret=$?+test0!=$ret-a-d"$state_dir"&&+echo$head_name>"$state_dir/head-name"&&+echo$onto>"$state_dir/onto"&&+echo$orig_head>"$state_dir/orig-head"&&+echo"$GIT_QUIET">"$state_dir/quiet"+exit$ret
@@ -329,14 +323,12 @@ thenshiftupstream=`gitrev-parse--verify"${upstream_name}^0"`||die"invalid upstream $upstream_name"-unsetroot_flagupstream_arg="$upstream_name"elsetest-z"$onto"&&die"You must specify --onto when using --root"unsetupstream_nameunsetupstream-root_flag="--root"-upstream_arg="$root_flag"+upstream_arg=--rootfi# Make sure the branch to rebase onto is valid.
@@ -461,23 +453,4 @@ elserevisions="$upstream..$orig_head"fi-iftest-z"$do_merge"-then-gitformat-patch-k--stdout--full-index--ignore-if-in-upstream\---src-prefix=a/--dst-prefix=b/\---no-renames$root_flag"$revisions"|-gitam$git_am_opt--rebasing--resolvemsg="$RESOLVEMSG"&&-move_to_original_branch-ret=$?-test0!=$ret-a-d"$apply_dir"&&-echo$head_name>"$apply_dir/head-name"&&-echo$onto>"$apply_dir/onto"&&-echo$orig_head>"$apply_dir/orig-head"&&-echo"$GIT_QUIET">"$apply_dir/quiet"-exit$ret-fi--# start doing a rebase with git-merge-# this is rename-aware if the recursive (default) strategy is used- run_specific_rebase
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Extract the code for merge-based rebase to git-rebase--merge.sh.
Signed-off-by: Martin von Zweigbergk <redacted>
---
What copyright year? Most of the code is just extracted from
git-rebase.sh, which has copyright year 2005. Does that matter?
Would read_initial_state be a better name than read_basic_state?
.gitignore | 1 +
Makefile | 1 +
git-rebase--merge.sh | 154 ++++++++++++++++++++++++++++++++++++++++++++++
git-rebase.sh | 167 +++++---------------------------------------------
4 files changed, 171 insertions(+), 152 deletions(-)
create mode 100644 git-rebase--merge.sh
@@ -0,0 +1,154 @@+#!/bin/sh+#+# Copyright (c) 2010 Junio C Hamano.+#++.git-sh-setup++prec=4++read_state(){+onto_name=$(cat"$state_dir"/onto_name)&&+end=$(cat"$state_dir"/end)&&+msgnum=$(cat"$state_dir"/msgnum)+}++continue_merge(){+test-d"$state_dir"||die"$state_dir directory does not exist"++unmerged=$(gitls-files-u)+iftest-n"$unmerged"+then+echo"You still have unmerged paths in your index"+echo"did you forget to use git add?"+die"$RESOLVEMSG"+fi++cmt=`cat"$state_dir/current"`+if!gitdiff-index--quiet--ignore-submodulesHEAD--+then+if!gitcommit--no-verify-C"$cmt"+then+echo"Commit failed, please do not call \"git commit\""+echo"directly, but instead do one of the following: "+die"$RESOLVEMSG"+fi+iftest-z"$GIT_QUIET"+then+printf"Committed: %0${prec}d "$msgnum+fi+echo"$cmt$(gitrev-parseHEAD^0)">>"$state_dir/rewritten"+else+iftest-z"$GIT_QUIET"+then+printf"Already applied: %0${prec}d "$msgnum+fi+fi+test-z"$GIT_QUIET"&&+GIT_PAGER=''gitlog--format=%s-1"$cmt"++# onto the next patch:+msgnum=$(($msgnum+1))+echo"$msgnum">"$state_dir/msgnum"+}++call_merge(){+cmt="$(cat"$state_dir/cmt.$1")"+echo"$cmt">"$state_dir/current"+hd=$(gitrev-parse--verifyHEAD)+cmt_name=$(gitsymbolic-refHEAD2>/dev/null||echoHEAD)+msgnum=$(cat"$state_dir/msgnum")+evalGITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'+evalGITHEAD_$hd='$onto_name'+exportGITHEAD_$cmtGITHEAD_$hd+iftest-n"$GIT_QUIET"+then+GIT_MERGE_VERBOSITY=1&&exportGIT_MERGE_VERBOSITY+fi+test-z"$strategy"&&strategy=recursive+eval'git-merge-$strategy'$strategy_opts'"$cmt^" -- "$hd" "$cmt"'+rv=$?+case"$rv"in+0)+unsetGITHEAD_$cmtGITHEAD_$hd+return+;;+1)+gitrerere$allow_rerere_autoupdate+die"$RESOLVEMSG"+;;+2)+echo"Strategy: $rv$strategy failed, try another"1>&2+die"$RESOLVEMSG"+;;+*)+die"Unknown exit code ($rv) from command:"\+"git-merge-$strategy$cmt^ -- HEAD $cmt"+;;+esac+}++finish_rb_merge(){+move_to_original_branch+gitnotescopy--for-rewrite=rebase<"$state_dir"/rewritten+iftest-x"$GIT_DIR"/hooks/post-rewrite&&+test-s"$state_dir"/rewritten;then+"$GIT_DIR"/hooks/post-rewriterebase<"$state_dir"/rewritten+fi+rm-r"$state_dir"+sayAlldone.+}++case"$action"in+continue)+read_state+continue_merge+whiletest"$msgnum"-le"$end"+do+call_merge"$msgnum"+continue_merge+done+finish_rb_merge+exit+;;+skip)+read_state+gitrerereclear+msgnum=$(($msgnum+1))+whiletest"$msgnum"-le"$end"+do+call_merge"$msgnum"+continue_merge+done+finish_rb_merge+exit+;;+esac++mkdir-p"$state_dir"+echo"$onto_name">"$state_dir/onto_name"+echo"$head_name">"$state_dir/head-name"+echo"$onto">"$state_dir/onto"+echo"$orig_head">"$state_dir/orig-head"+echo"$GIT_QUIET">"$state_dir/quiet"++msgnum=0+forcmtin`gitrev-list--reverse--no-merges"$revisions"`+do+msgnum=$(($msgnum+1))+echo"$cmt">"$state_dir/cmt.$msgnum"+done++echo1>"$state_dir/msgnum"+echo$msgnum>"$state_dir/end"++end=$msgnum+msgnum=1++whiletest"$msgnum"-le"$end"+do+call_merge"$msgnum"+continue_merge+done++finish_rb_merge
@@ -68,94 +67,13 @@ preserve_merges=autosquash=test"$(gitconfig--boolrebase.autosquash)"="true"&&autosquash=t-read_state(){-iftest"$type"=merge-then-onto_name=$(cat"$state_dir"/onto_name)&&-end=$(cat"$state_dir"/end)&&-msgnum=$(cat"$state_dir"/msgnum)-fi&&+read_basic_state(){head_name=$(cat"$state_dir"/head-name)&&onto=$(cat"$state_dir"/onto)&&orig_head=$(cat"$state_dir"/orig-head)&&GIT_QUIET=$(cat"$state_dir"/quiet)}-continue_merge(){-test-d"$merge_dir"||die"$merge_dir directory does not exist"--unmerged=$(gitls-files-u)-iftest-n"$unmerged"-then-echo"You still have unmerged paths in your index"-echo"did you forget to use git add?"-die"$RESOLVEMSG"-fi--cmt=`cat"$merge_dir/current"`-if!gitdiff-index--quiet--ignore-submodulesHEAD---then-if!gitcommit--no-verify-C"$cmt"-then-echo"Commit failed, please do not call \"git commit\""-echo"directly, but instead do one of the following: "-die"$RESOLVEMSG"-fi-iftest-z"$GIT_QUIET"-then-printf"Committed: %0${prec}d "$msgnum-fi-echo"$cmt$(gitrev-parseHEAD^0)">>"$merge_dir/rewritten"-else-iftest-z"$GIT_QUIET"-then-printf"Already applied: %0${prec}d "$msgnum-fi-fi-test-z"$GIT_QUIET"&&-GIT_PAGER=''gitlog--format=%s-1"$cmt"--# onto the next patch:-msgnum=$(($msgnum+1))-echo"$msgnum">"$merge_dir/msgnum"-}--call_merge(){-cmt="$(cat"$merge_dir/cmt.$1")"-echo"$cmt">"$merge_dir/current"-hd=$(gitrev-parse--verifyHEAD)-cmt_name=$(gitsymbolic-refHEAD2>/dev/null||echoHEAD)-msgnum=$(cat"$merge_dir/msgnum")-evalGITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'-evalGITHEAD_$hd='$onto_name'-exportGITHEAD_$cmtGITHEAD_$hd-iftest-n"$GIT_QUIET"-then-GIT_MERGE_VERBOSITY=1&&exportGIT_MERGE_VERBOSITY-fi-test-z"$strategy"&&strategy=recursive-eval'git-merge-$strategy'$strategy_opts'"$cmt^" -- "$hd" "$cmt"'-rv=$?-case"$rv"in-0)-unsetGITHEAD_$cmtGITHEAD_$hd-return-;;-1)-gitrerere$allow_rerere_autoupdate-die"$RESOLVEMSG"-;;-2)-echo"Strategy: $rv$strategy failed, try another"1>&2-die"$RESOLVEMSG"-;;-*)-die"Unknown exit code ($rv) from command:"\-"git-merge-$strategy$cmt^ -- HEAD $cmt"-;;-esac-}- move_to_original_branch(){case"$head_name"inrefs/*)
@@ -343,7 +253,7 @@ test $# -gt 2 && usageiftest-n"$action"thentest-z"$in_progress"&&die"No rebase in progress?"-test"$type"=interactive&&run_interactive_rebase+test"$type"=interactive&&run_specific_rebaseficase"$action"in
@@ -354,44 +264,23 @@ continue)echo"mark them as resolved using git add"exit1}-read_state-iftest-d"$merge_dir"-then-continue_merge-whiletest"$msgnum"-le"$end"-do-call_merge"$msgnum"-continue_merge-done-finish_rb_merge-exit-fi+read_basic_state+run_specific_rebasegitam--resolved--3way--resolvemsg="$RESOLVEMSG"&&move_to_original_branchexit;; skip)gitreset--hardHEAD||exit$?-read_state-iftest-d"$merge_dir"-then-gitrerereclear-msgnum=$(($msgnum+1))-whiletest"$msgnum"-le"$end"-do-call_merge"$msgnum"-continue_merge-done-finish_rb_merge-exit-fi+read_basic_state+run_specific_rebasegitam-3--skip--resolvemsg="$RESOLVEMSG"&&move_to_original_branchexit;; abort)gitrerereclear-read_state+read_basic_statecase"$head_name"inrefs/*)gitsymbolic-refHEAD$head_name||
@@ -549,7 +438,7 @@ thenGIT_PAGER=''gitdiff--stat--summary"$mb""$onto"fi-test"$type"=interactive&&run_interactive_rebase+test"$type"=interactive&&run_specific_rebase# Detach HEAD and reset the tree say"First, rewinding head to replay your work on top of it..."
@@ -591,30 +480,4 @@ fi# start doing a rebase with git-merge# this is rename-aware if the recursive (default) strategy is used-mkdir-p"$merge_dir"-echo"$onto_name">"$merge_dir/onto_name"-echo"$head_name">"$merge_dir/head-name"-echo"$onto">"$merge_dir/onto"-echo"$orig_head">"$merge_dir/orig-head"-echo"$GIT_QUIET">"$merge_dir/quiet"--msgnum=0-forcmtin`gitrev-list--reverse--no-merges"$revisions"`-do-msgnum=$(($msgnum+1))-echo"$cmt">"$merge_dir/cmt.$msgnum"-done--echo1>"$merge_dir/msgnum"-echo$msgnum>"$merge_dir/end"--end=$msgnum-msgnum=1--whiletest"$msgnum"-le"$end"-do-call_merge"$msgnum"-continue_merge-done--finish_rb_merge+run_specific_rebase
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Factor out the common parts of the handling of the sub commands
'--continue', '--skip' and '--abort'. The '--abort' handling can
handled completely in git-rebase.sh.
After this refactoring, the calls to git-rebase--am.sh,
git-rebase--merge.sh and git-rebase--interactive.sh will be better
aligned. There will only be one call to interactive rebase that will
shortcut the very last part of git-rebase.sh.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 34 +++-------------------------------
git-rebase.sh | 17 +++++++++++++++--
2 files changed, 18 insertions(+), 33 deletions(-)
@@ -655,14 +653,6 @@ rearrange_squash () {case"$action"incontinue)get_saved_options-comment_for_reflogcontinue--# Sanity check-gitrev-parse--verifyHEAD>/dev/null||-die"Cannot read HEAD"-gitupdate-index--ignore-submodules--refresh&&-gitdiff-files--quiet--ignore-submodules||-die"Working tree is dirty"# do we have anything to commit?ifgitdiff-index--cached--quiet--ignore-submodulesHEAD--
@@ -693,30 +683,12 @@ first and then run 'git rebase --continue' again."require_clean_work_tree"rebase"do_rest;;-abort)-get_saved_options-comment_for_reflogabort--gitrerereclear--head_name=$(cat"$state_dir"/head-name)-orig_head=$(cat"$state_dir"/head)-case$head_namein-refs/*)-gitsymbolic-refHEAD$head_name-;;-esac&&-outputgitreset--hard$orig_head&&-rm-rf"$state_dir"-exit-;; skip)get_saved_options-comment_for_reflogskipgitrerereclear-outputgitreset--hard&&do_rest+do_rest;;esac
@@ -267,11 +272,19 @@ test $# -gt 2 && usageiftest-n"$action"thentest-z"$in_progress"&&die"No rebase in progress?"-test"$type"=interactive&&run_specific_rebase+# Only interactive rebase uses detailed reflog messages+iftest"$type"=interactive&&test"$GIT_REFLOG_ACTION"=rebase+then+GIT_REFLOG_ACTION="rebase -i ($action)"+exportGIT_REFLOG_ACTION+fificase"$action"incontinue)+# Sanity check+gitrev-parse--verifyHEAD>/dev/null||+die"Cannot read HEAD"gitupdate-index--ignore-submodules--refresh&&gitdiff-files--quiet--ignore-submodules||{echo"You must edit all merge conflicts and then"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
The variables $branch and $orig_head were used as synonyms. To avoid
confusion, remove $branch. The name 'orig_head' seems more suitable,
since that is the name used when the variable is persisted.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase.sh | 19 +++++++++----------
1 files changed, 9 insertions(+), 10 deletions(-)
@@ -487,10 +487,10 @@ case "$#" inswitch_to="$1"ifgitshow-ref--verify--quiet--"refs/heads/$1"&&-branch=$(gitrev-parse-q--verify"refs/heads/$1")+orig_head=$(gitrev-parse-q--verify"refs/heads/$1")thenhead_name="refs/heads/$1"-elifbranch=$(gitrev-parse-q--verify"$1")+eliforig_head=$(gitrev-parse-q--verify"$1")thenhead_name="detached HEAD"else
@@ -507,24 +507,23 @@ case "$#" inhead_name="detached HEAD"branch_name=HEAD;# detachedfi-branch=$(gitrev-parse--verify"${branch_name}^0")||exit+orig_head=$(gitrev-parse--verify"${branch_name}^0")||exit;;esac-orig_head=$branch require_clean_work_tree"rebase""Please commit or stash them."-# Now we are rebasing commits $upstream..$branch (or with --root,-# everything leading up to $branch) on top of $onto+# Now we are rebasing commits $upstream..$orig_head (or with --root,+# everything leading up to $orig_head) on top of $onto# Check if we are already based on $onto with linear history,# but this should be done only when upstream and onto are the same# and if this is not an interactive rebase.-mb=$(gitmerge-base"$onto""$branch")+mb=$(gitmerge-base"$onto""$orig_head")iftest"$type"!=interactive&&test"$upstream"="$onto"&&test"$mb"="$onto"&&# linear history?-!(gitrev-list--parents"$onto".."$branch"|sane_grep" .* ")>/dev/null+!(gitrev-list--parents"$onto".."$orig_head"|sane_grep" .* ")>/dev/nulltheniftest-z"$force_rebase"then
@@ -555,11 +554,11 @@ test "$type" = interactive && run_interactive_rebase# Detach HEAD and reset the tree say"First, rewinding head to replay your work on top of it..." gitcheckout-q"$onto^0"||die"could not detach HEAD"-gitupdate-refORIG_HEAD$branch+gitupdate-refORIG_HEAD$orig_head# If the $onto is a proper descendant of the tip of the branch, then# we just fast-forwarded.-iftest"$mb"="$branch"+iftest"$mb"="$orig_head"thensay"Fast-forwarded $branch_name to $onto_name."move_to_original_branch
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
When rebase stops due to conflict, interactive rebase currently
displays a different hint to the user than non-interactive rebase
does. Use the same message for both types of rebase.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Should we include the "mark the corrected paths with 'git add
<paths>'" part?
git-rebase--interactive.sh | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Rename variables HEAD and OLDHEAD to orig_head and HEADNAME to
head_name, which are the names used in git-rebase.sh. This prepares
for factoring out of the code that persists these variables during the
entire rebase process. Using the same variable names to mean the same
thing in both files also makes the code easier to read.
While at it, also remove the DOTEST variable and use the state_dir
variable that was inherited from git-rebase.sh instead.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Squash this commit with earlier commit that also renamed variables in
git-rebase--interactive.sh?
git-rebase--interactive.sh | 120 +++++++++++++++++++++----------------------
1 files changed, 59 insertions(+), 61 deletions(-)
@@ -12,22 +12,20 @@ .git-sh-setup-DOTEST="$GIT_DIR/rebase-merge"-# The file containing rebase commands, comments, and empty lines.# This file is created by "git rebase -i" then edited by the user. As# the lines are processed, they are removed from the front of this# file and written to the tail of $DONE.-TODO="$DOTEST"/git-rebase-todo+TODO="$state_dir"/git-rebase-todo# The rebase command lines that have already been processed. A line# is moved here when it is first handled, before any associated user# actions.-DONE="$DOTEST"/done+DONE="$state_dir"/done# The commit message that is planned to be used for any changes that# need to be committed following a user interaction.-MSG="$DOTEST"/message+MSG="$state_dir"/message# The file into which is accumulated the suggested commit message for# squash/fixup commands. When the first of a series of squash/fixups
@@ -42,14 +40,14 @@ MSG="$DOTEST"/message# written to the file so far (including the initial "pick" commit).# Each time that a commit message is processed, this line is read and# updated. It is deleted just before the combined commit is made.-SQUASH_MSG="$DOTEST"/message-squash+SQUASH_MSG="$state_dir"/message-squash# If the current series of squash/fixups has not yet included a squash# command, then this file exists and holds the commit message of the# original "pick" commit. (If the series ends without a "squash"# command, then this can be used as the commit message of the combined# commit without opening the editor.)-FIXUP_MSG="$DOTEST"/message-fixup+FIXUP_MSG="$state_dir"/message-fixup# $REWRITTEN is the name of a directory containing files for each# commit that is reachable by at least one merge base of $HEAD and
@@ -57,14 +55,14 @@ FIXUP_MSG="$DOTEST"/message-fixup# might be. This ensures that commits on merged, but otherwise# unrelated side branches are left alone. (Think "X" in the man page's# example.)-REWRITTEN="$DOTEST"/rewritten+REWRITTEN="$state_dir"/rewritten-DROPPED="$DOTEST"/dropped+DROPPED="$state_dir"/dropped# A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and# GIT_AUTHOR_DATE that will be used for the commit that is currently# being rebased.-AUTHOR_SCRIPT="$DOTEST"/author-script+AUTHOR_SCRIPT="$state_dir"/author-script# When an "edit" rebase command is being processed, the SHA1 of the# commit to be edited is recorded in this file. When "git rebase
@@ -72,14 +70,14 @@ AUTHOR_SCRIPT="$DOTEST"/author-script# will be amended to the HEAD commit, but only provided the HEAD# commit is still the commit to be edited. When any other rebase# command is processed, this file is deleted.-AMEND="$DOTEST"/amend+AMEND="$state_dir"/amend# For the post-rewrite hook, we make a list of rewritten commits and# their new sha1s. The rewritten-pending list keeps the sha1s of# commits that have been processed, but not committed yet,# e.g. because they are waiting for a 'squash' command.-REWRITTEN_LIST="$DOTEST"/rewritten-list-REWRITTEN_PENDING="$DOTEST"/rewritten-pending+REWRITTEN_LIST="$state_dir"/rewritten-list+REWRITTEN_PENDING="$state_dir"/rewritten-pendingGIT_CHERRY_PICK_HELP="$RESOLVEMSG"exportGIT_CHERRY_PICK_HELP
@@ -205,20 +203,20 @@ pick_one_preserving_merges () {esacsha1=$(gitrev-parse$sha1)-iftest-f"$DOTEST"/current-commit+iftest-f"$state_dir"/current-committheniftest"$fast_forward"=tthenwhilereadcurrent_commitdogitrev-parseHEAD>"$REWRITTEN"/$current_commit-done<"$DOTEST"/current-commit-rm"$DOTEST"/current-commit||+done<"$state_dir"/current-commit+rm"$state_dir"/current-commit||die"Cannot write current commit's replacement sha1"fifi-echo$sha1>>"$DOTEST"/current-commit+echo$sha1>>"$state_dir"/current-commit# rewrite parents; if none were rewritten, we can fast-forward.new_parents=
@@ -425,7 +423,7 @@ do_next () {mark_action_donepick_one$sha1||die_with_patch$sha1"Could not apply $sha1... $rest"-echo"$sha1">"$DOTEST"/stopped-sha+echo"$sha1">"$state_dir"/stopped-shamake_patch$sha1gitrev-parse--verifyHEAD>"$AMEND"warn"Stopped at $sha1... $rest"
@@ -490,7 +488,7 @@ do_next () {printf'Executing: %s\n'"$rest"# "exec" command doesn't take a sha1 in the todo-list.# => can't just use $sha1 here.-gitrev-parse--verifyHEAD>"$DOTEST"/stopped-sha+gitrev-parse--verifyHEAD>"$state_dir"/stopped-sha${SHELL:-@SHELL_PATH@}-c"$rest"# Actual executionstatus=$?iftest"$status"-ne0
@@ -549,9 +547,9 @@ do_next () {"$GIT_DIR"/hooks/post-rewriterebase<"$REWRITTEN_LIST"true# we don't care if this hook failedfi&&-rm-rf"$DOTEST"&&+rm-rf"$state_dir"&&gitgc--auto&&-warn"Successfully rebased and updated $HEADNAME."+warn"Successfully rebased and updated $head_name."exit}
@@ -602,9 +600,9 @@ skip_unnecessary_picks () { get_saved_options(){test-d"$REWRITTEN"&&preserve_merges=t-test-f"$DOTEST"/strategy&&strategy="$(cat"$DOTEST"/strategy)"-test-f"$DOTEST"/verbose&&verbose=t-test-f"$DOTEST"/rebase-root&&rebase_root=t+test-f"$state_dir"/strategy&&strategy="$(cat"$state_dir"/strategy)"+test-f"$state_dir"/verbose&&verbose=t+test-f"$state_dir"/rebase-root&&rebase_root=t}# Rearrange the todo list that has both "pick sha1 msg" and
@@ -704,7 +702,7 @@ first and then run 'git rebase --continue' again."}fi-record_in_rewritten"$(cat"$DOTEST"/stopped-sha)"+record_in_rewritten"$(cat"$state_dir"/stopped-sha)"require_clean_work_tree"rebase"do_rest
@@ -747,28 +745,28 @@ thendie"Could not checkout $switch_to"fi-HEAD=$(gitrev-parse--verifyHEAD)||die"No HEAD?"-mkdir"$DOTEST"||die"Could not create temporary $DOTEST"+orig_head=$(gitrev-parse--verifyHEAD)||die"No HEAD?"+mkdir"$state_dir"||die"Could not create temporary $state_dir"-:>"$DOTEST"/interactive||die"Could not mark as interactive"-echo"$head_name">"$DOTEST"/head-name+:>"$state_dir"/interactive||die"Could not mark as interactive"+echo"$head_name">"$state_dir"/head-name-echo$HEAD>"$DOTEST"/head+echo$orig_head>"$state_dir"/headcase"$rebase_root"in'')-rm-f"$DOTEST"/rebase-root;;+rm-f"$state_dir"/rebase-root;; *)-:>"$DOTEST"/rebase-root;;+:>"$state_dir"/rebase-root;;esac-echo$onto>"$DOTEST"/onto-test-z"$strategy"||echo"$strategy">"$DOTEST"/strategy-testt="$verbose"&&:>"$DOTEST"/verbose+echo$onto>"$state_dir"/onto+test-z"$strategy"||echo"$strategy">"$state_dir"/strategy+testt="$verbose"&&:>"$state_dir"/verboseiftestt="$preserve_merges"theniftest-z"$rebase_root"thenmkdir"$REWRITTEN"&&-forcin$(gitmerge-base--all$HEAD$upstream)+forcin$(gitmerge-base--all$orig_head$upstream)doecho$onto>"$REWRITTEN"/$c||die"Could not init rewritten commits"
@@ -782,21 +780,21 @@ then# parents to rewrite and skipping dropped commits would# prematurely end our probeMERGES_OPTION=-first_after_upstream="$(gitrev-list--reverse--first-parent$upstream..$HEAD|head-n1)"+first_after_upstream="$(gitrev-list--reverse--first-parent$upstream..$orig_head|head-n1)"elseMERGES_OPTION="--no-merges --cherry-pick"fi-SHORTHEAD=$(gitrev-parse--short$HEAD)+SHORTHEAD=$(gitrev-parse--short$orig_head)SHORTONTO=$(gitrev-parse--short$onto)iftest-z"$rebase_root"# this is now equivalent to ! -z "$upstream"thenSHORTUPSTREAM=$(gitrev-parse--short$upstream)-REVISIONS=$upstream...$HEAD+REVISIONS=$upstream...$orig_headSHORTREVISIONS=$SHORTUPSTREAM..$SHORTHEADelse-REVISIONS=$onto...$HEAD+REVISIONS=$onto...$orig_headSHORTREVISIONS=$SHORTHEADfi gitrev-list$MERGES_OPTION--pretty=oneline--abbrev-commit\
@@ -837,13 +835,13 @@ thenmkdir"$DROPPED"# Save all non-cherry-picked changesgitrev-list$REVISIONS--left-right--cherry-pick|\-sed-n"s/^>//p">"$DOTEST"/not-cherry-picks+sed-n"s/^>//p">"$state_dir"/not-cherry-picks# Now all commits and note which ones are missing in# not-cherry-picks and hence being droppedgitrev-list$REVISIONS|whilereadrevdo-iftest-f"$REWRITTEN"/$rev-a"$(sane_grep"$rev""$DOTEST"/not-cherry-picks)"=""+iftest-f"$REWRITTEN"/$rev-a"$(sane_grep"$rev""$state_dir"/not-cherry-picks)"=""then# Use -f2 because if rev-list is telling us this commit is# not worthwhile, we don't want to track its multiple heads,
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
When the merge strategy fails, a message suggesting the user to try
another strategy is displayed. Remove the "$rv" (which is always equal
to "2" in this case) from that message.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--merge.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
To make it possible to later remove the handling of --abort from
git-rebase--interactive.sh, align the implementation in git-rebase.sh
with the former by making it a bit more verbose.
Signed-off-by: Martin von Zweigbergk <redacted>
---
What do we really want to print when -v is passed? Interactive rebase
is currently quite a bit more verbose than non-interactive rebase.
git-rebase--interactive.sh | 14 --------------
git-rebase.sh | 20 +++++++++++++++++---
2 files changed, 17 insertions(+), 17 deletions(-)
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
The code reading the state saved in $merge_dir or $rebase_dir is
currently spread out in many places, making it harder to read and to
introduce additional state. Extract this code into one method that reads
the state.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase.sh | 53 +++++++++++++++++++++++------------------------------
1 files changed, 23 insertions(+), 30 deletions(-)
@@ -57,6 +57,22 @@ rebase_root=force_rebase=allow_rerere_autoupdate=+read_state(){+iftest-d"$merge_dir"+then+state_dir="$merge_dir"+prev_head=$(cat"$merge_dir"/prev_head)&&+end=$(cat"$merge_dir"/end)&&+msgnum=$(cat"$merge_dir"/msgnum)+else+state_dir="$apply_dir"+fi&&+head_name=$(cat"$state_dir"/head-name)&&+onto=$(cat"$state_dir"/onto)&&+orig_head=$(cat"$state_dir"/orig-head)&&+GIT_QUIET=$(cat"$state_dir"/quiet)+}+ continue_merge(){test-n"$prev_head"||die"prev_head must be defined"test-d"$merge_dir"||die"$merge_dir directory does not exist"
@@ -220,13 +232,9 @@ doecho"mark them as resolved using git add"exit1}+read_stateiftest-d"$merge_dir"then-prev_head=$(cat"$merge_dir/prev_head")-end=$(cat"$merge_dir/end")-msgnum=$(cat"$merge_dir/msgnum")-onto=$(cat"$merge_dir/onto")-GIT_QUIET=$(cat"$merge_dir/quiet")continue_mergewhiletest"$msgnum"-le"$end"do
@@ -249,15 +253,11 @@ dodie"No rebase in progress?"gitreset--hardHEAD||exit$?+read_stateiftest-d"$merge_dir"thengitrerereclear-prev_head=$(cat"$merge_dir/prev_head")-end=$(cat"$merge_dir/end")-msgnum=$(cat"$merge_dir/msgnum")msgnum=$(($msgnum+1))-onto=$(cat"$merge_dir/onto")-GIT_QUIET=$(cat"$merge_dir/quiet")whiletest"$msgnum"-le"$end"docall_merge"$msgnum"
@@ -279,18 +275,15 @@ dodie"No rebase in progress?"gitrerereclear--test-d"$merge_dir"||merge_dir="$apply_dir"--head_name="$(cat"$merge_dir"/head-name)"&&+read_statecase"$head_name"inrefs/*)gitsymbolic-refHEAD$head_name||die"Could not move back to $head_name";;esac-gitreset--hard$(cat"$merge_dir/orig-head")-rm-r"$merge_dir"+gitreset--hard$orig_head+rm-r"$state_dir"exit;;--onto)
@@ -573,12 +566,12 @@ fi# this is rename-aware if the recursive (default) strategy is used mkdir-p"$merge_dir"-echo"$onto">"$merge_dir/onto"echo"$onto_name">"$merge_dir/onto_name"prev_head=$orig_headecho"$prev_head">"$merge_dir/prev_head"-echo"$orig_head">"$merge_dir/orig-head"echo"$head_name">"$merge_dir/head-name"+echo"$onto">"$merge_dir/onto"+echo"$orig_head">"$merge_dir/orig-head"echo"$GIT_QUIET">"$merge_dir/quiet"msgnum=0
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Remove the parsing and validation of references (onto, upstream, branch)
from git-rebase--interactive.sh and rely on the information exported from
git-rebase.sh.
By using the parsing of the --onto parameter in git-rebase.sh, this
improves the error message when the parameter is invalid.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Should the check for set GIT_COMMITTER_IDENT be done for
non-interactive rebase as well or does it only make sense for
interactive rebase?
git-rebase--interactive.sh | 48 +++----------------------------------------
git-rebase.sh | 12 ++++++----
2 files changed, 11 insertions(+), 49 deletions(-)
@@ -769,47 +750,26 @@ skip);;esac-iftest-n"$onto"-then-onto=$(parse_onto"$onto")||die"Does not point to a valid commit: $1"-fi--test-z"$rebase_root"-a$#-ge1-a$#-le2||-test!-z"$rebase_root"-a$#-le1||usage- gitvarGIT_COMMITTER_IDENT>/dev/null||die"You need to set your committer info first"-iftest-z"$rebase_root"-then-upstream_arg="$1"-upstream=$(gitrev-parse--verify"$1")||die"Invalid base"-test-z"$onto"&&onto=$upstream-shift-else-upstream=-upstream_arg=--root-test-z"$onto"&&-die"You must specify --onto when using --root"-fi require_clean_work_tree"rebase""Please commit or stash them." run_pre_rebase_hook"$upstream_arg""$@" comment_for_reflogstart-iftest!-z"$1"+iftest!-z"$switch_to"then-outputgitcheckout"$1"||-die"Could not checkout $1"+outputgitcheckout"$switch_to"||+die"Could not checkout $switch_to"fiHEAD=$(gitrev-parse--verifyHEAD)||die"No HEAD?" mkdir"$DOTEST"||die"Could not create temporary $DOTEST" :>"$DOTEST"/interactive||die"Could not mark as interactive"-gitsymbolic-refHEAD>"$DOTEST"/head-name2>/dev/null||-echo"detached HEAD">"$DOTEST"/head-name+echo"$head_name">"$DOTEST"/head-nameecho$HEAD>"$DOTEST"/headcase"$rebase_root"in
@@ -433,8 +434,6 @@ elsestate_dir="$apply_dir"fi-test"$type"=interactive&&run_interactive_rebase"$@"-iftest-z"$rebase_root"then# The upstream head must be given. Make sure it is valid.
@@ -445,7 +444,7 @@ thenunsetroot_flagupstream_arg="$upstream_name"else-test-z"$onto"&&die"--root must be used with --onto"+test-z"$onto"&&die"You must specify --onto when using --root"unsetupstream_nameunsetupstreamroot_flag="--root"
@@ -472,7 +471,8 @@ case "$onto_name" infi;; *)-onto=$(gitrev-parse--verify"${onto_name}^0")||exit+onto=$(gitrev-parse--verify"${onto_name}^0")||+die"Does not point to a valid commit: $1";;esac
@@ -513,6 +513,8 @@ case "$#" inesacorig_head=$branch+test"$type"=interactive&&run_interactive_rebase"$@"+ require_clean_work_tree"rebase""Please commit or stash them."# Now we are rebasing commits $upstream..$branch (or with --root,
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Extrace the code for writing the state to rebase-apply/ or
rebase-merge/ when a rebase is initiated. This will make it easier to
later make both interactive and non-interactive rebase remember the
options used.
Note that non-interactive rebase stores the sha1 of the original head
in a file called orig-head, while interactive rebase stores it in a
file called head.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--am.sh | 6 +-----
git-rebase--interactive.sh | 5 +----
git-rebase--merge.sh | 5 +----
git-rebase.sh | 16 ++++++++++++++--
4 files changed, 17 insertions(+), 15 deletions(-)
@@ -707,16 +707,13 @@ orig_head=$(git rev-parse --verify HEAD) || die "No HEAD?" mkdir"$state_dir"||die"Could not create temporary $state_dir" :>"$state_dir"/interactive||die"Could not mark as interactive"-echo"$head_name">"$state_dir"/head-name--echo$orig_head>"$state_dir"/head+write_basic_statecase"$rebase_root"in'')rm-f"$state_dir"/rebase-root;; *):>"$state_dir"/rebase-root;;esac-echo$onto>"$state_dir"/ontotest-z"$strategy"||echo"$strategy">"$state_dir"/strategytestt="$verbose"&&:>"$state_dir"/verboseiftestt="$preserve_merges"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
If '--[no-]allow_rerere_autoupdate' is passed when 'git rebase -m' is
called and a merge conflict occurs, the flag will be forgotten for the
rest of the rebase process. Make rebase remember it by saving the
value.
Signed-off-by: Martin von Zweigbergk <redacted>
---
allow_rerere_autoupdate is only used by git-rebase--merge. Still ok to
write and read it here?
Should allow_rerere_autoupdate also be added to git_am_opt?
git-rebase.sh | 4 ++++
t/t3418-rebase-continue.sh | 21 +++++++++++++++++++++
2 files changed, 25 insertions(+), 0 deletions(-)
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Currently, only interactive rebase remembers the value of the '-v'
flag from the initial invocation. Make non-interactive rebase also
remember it.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 2 --
git-rebase.sh | 6 ++++--
2 files changed, 4 insertions(+), 4 deletions(-)
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Since 8e4a91b (rebase -i: remember the settings of -v, -s and -p when
interrupted, 2007-07-08), the variable preserve_merges (then called
PRESERVE_MERGES) was detected from the state saved in
$GIT_DIR/rebase-merge in order to be used when the rebase resumed, but
its value was never actually used. The variable's value was only used
when the rebase was initated.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 5 -----
1 files changed, 0 insertions(+), 5 deletions(-)
@@ -650,8 +649,6 @@ rearrange_squash () {case"$action"incontinue)-get_saved_options-# do we have anything to commit?ifgitdiff-index--cached--quiet--ignore-submodulesHEAD--then
@@ -682,8 +679,6 @@ first and then run 'git rebase --continue' again."do_rest;; skip)-get_saved_options-gitrererecleardo_rest
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
The 'onto_name' state used in 'git rebase --merge' is currently read
once for each commit that need to be applied. It doesn't change
between each iteration, however, so it should be moved out of the
loop. This also makes the code more readable. Also remove the unused
variable 'end'.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase.sh | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
The sub commands '--continue', '--skip' or '--abort' may only be used
standalone according to the documentation. Other options following the
sub command are currently not accepted, but options preceeding them
are. For example, 'git rebase --continue -v' is not accepted, while
'git rebase -v --continue' is. Tighten up the check and allow no other
options when one of these sub commands are used.
Only check that it is standalone for non-interactive rebase for
now. Once the command line processing for interactive rebase has been
replaced by the command line processing in git-rebase.sh, this check
will also apply to interactive rebase.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Is this too simplistic? Do we forsee that we want to support passing
options when resuming a rebase? Is it better to check for each other
option that it is not passed (i.e. no '-v', no '-s' etc.)?
Might some users be depending on the current behavior, even though it
is undocumented?
git-rebase.sh | 4 ++--
t/t3403-rebase-skip.sh | 5 +++++
t/t3407-rebase-abort.sh | 10 ++++++++++
t/t3418-rebase-continue.sh | 5 +++++
4 files changed, 22 insertions(+), 2 deletions(-)
@@ -35,6 +35,11 @@ test_expect_success 'rebase with git am -3 (default)' 'test_must_failgitrebasemaster'+test_expect_success'rebase --skip can not be used with other options''+test_must_failgitrebase-v--skip&&+test_must_failgitrebase--skip-v+'+ test_expect_success'rebase --skip with am -3''gitrebase--skip'
@@ -84,6 +84,16 @@ testrebase() {test_cmpreflog_beforereflog_after&&rmreflog_beforereflog_after'++test_expect_success'rebase --abort can not be used with other options''+cd"$work_dir"&&+# Clean up the state from the previous one+gitreset--hardpre-rebase&&+test_must_failgitrebase$typemaster&&+test_must_failgitrebase-v--abort&&+test_must_failgitrebase--abort-v&&+gitrebase--abort+'} testrebase"".git/rebase-apply
@@ -40,4 +40,9 @@ test_expect_success 'non-interactive rebase --continue works with touched file'gitrebase--continue'+test_expect_success'rebase --continue can not be used with other options''+test_must_failgitrebase-v--continue&&+test_must_failgitrebase--continue-v+'+ test_done
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
When a rebase is resumed, interactive rebase remembers any merge
strategy passed when the rebase was initated. Make non-interactive
rebase remember any merge strategy as well. Also make non-interactive
rebase remember any merge strategy options.
To be able to resume a rebase that was initiated with an older version
of git (older than this commit), make sure not to expect the saved
option files to exist.
Test case idea taken from Junio's 71fc224 (t3402: test "rebase
-s<strategy> -X<opt>", 2010-11-11).
Signed-off-by: Martin von Zweigbergk <redacted>
---
How to add support for strategy options to interactive rebase?
git-rebase--interactive.sh | 2 --
git-rebase.sh | 6 ++++++
t/t3418-rebase-continue.sh | 29 +++++++++++++++++++++++++++++
3 files changed, 35 insertions(+), 2 deletions(-)
@@ -713,7 +712,6 @@ case "$rebase_root" in *):>"$state_dir"/rebase-root;;esac-test-z"$strategy"||echo"$strategy">"$state_dir"/strategyiftestt="$preserve_merges"theniftest-z"$rebase_root"
@@ -45,4 +45,33 @@ test_expect_success 'rebase --continue can not be used with other options' 'test_must_failgitrebase--continue-v'+test_expect_success'rebase --continue remembers merge strategy and options''+rm-fr.git/rebase-*&&+gitreset--hardcommit-new-file-F2-on-topic-branch&&+test_commit"commit-new-file-F3-on-topic-branch"F332&&+test_when_finished"rm -fr test-bin funny.was.run"&&+mkdirtest-bin&&+cat>test-bin/git-merge-funny<<-EOF+#!$SHELL_PATH+case"\$1"in--opt);;*)exit2;;esac+shift&&+>funny.was.run&&+execgitmerge-recursive"\$@"+EOF+chmod+xtest-bin/git-merge-funny&&+(+PATH=./test-bin:$PATH+test_must_failgitrebase-sfunny-Xoptmastertopic+)&&+test-ffunny.was.run&&+rmfunny.was.run&&+echo"Resolved">F2&&+gitaddF2&&+(+PATH=./test-bin:$PATH+gitrebase--continue+)&&+test-ffunny.was.run+'+ test_done
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Before calling 'git cherry-pick', interactive rebase currently checks
if we are rebasing from root (if --root was passed). If we are, the
'--ff' flag to 'git cherry-pick' is omitted. However, according to the
documentation for 'git cherry-pick --ff', "If the current HEAD is the
same as the parent of the cherry-picked commit, then a fast forward to
this commit will be performed.". This should never be the case when
rebasing from root, so it should not matter whether --ff is passed, so
simplify the code by removing the condition.
Signed-off-by: Martin von Zweigbergk <redacted>
---
While factoring out the state writing code a few patches back, I went
through each of the pieces of state that was written. I was a bit
hesitant to include this patch since I'm not quite sure why the code
was introduced, but I thought I would include it anyway to hear what
you have to say.
There used to be bug when using --ff when rebasing a root commit. This
was fixed in 6355e50 (builtin/revert.c: don't dereference a NULL
pointer, 2010-09-27). Could this have been the reason for the check?
Thomas, do you remember?
git-rebase--interactive.sh | 15 ---------------
1 files changed, 0 insertions(+), 15 deletions(-)
@@ -582,10 +577,6 @@ skip_unnecessary_picks () {die"Could not skip unnecessary pick commands"}-get_saved_options(){-test-f"$state_dir"/rebase-root&&rebase_root=t-}-# Rearrange the todo list that has both "pick sha1 msg" and# "pick sha1 fixup!/squash! msg" appears in it so that the latter# comes immediately after the former, and change "pick" to
@@ -701,12 +692,6 @@ mkdir "$state_dir" || die "Could not create temporary $state_dir" :>"$state_dir"/interactive||die"Could not mark as interactive" write_basic_state-case"$rebase_root"in-'')-rm-f"$state_dir"/rebase-root;;-*)-:>"$state_dir"/rebase-root;;-esaciftestt="$preserve_merges"theniftest-z"$rebase_root"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Since 22db240 (git-am: propagate --3way options as well, 2008-12-04),
the --3way has been propageted across failure, so it is since
pointless to pass it to git-am when resuming.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--am.sh | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
Instead of using the old variable name 'dotest' for
"$GIT_DIR"/rebase-merge and no variable for "$GIT_DIR"/rebase-apply,
introduce two variables 'merge_dir' and 'apply_dir' for these paths.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase.sh | 141 +++++++++++++++++++++++++++++----------------------------
1 files changed, 71 insertions(+), 70 deletions(-)
@@ -58,7 +59,7 @@ allow_rerere_autoupdate= continue_merge(){test-n"$prev_head"||die"prev_head must be defined"-test-d"$dotest"||die"$dotest directory does not exist"+test-d"$merge_dir"||die"$merge_dir directory does not exist"unmerged=$(gitls-files-u)iftest-n"$unmerged"
@@ -93,22 +94,22 @@ continue_merge () {prev_head=`gitrev-parseHEAD^0`# save the resulting commit so we can read-tree on it later-echo"$prev_head">"$dotest/prev_head"+echo"$prev_head">"$merge_dir/prev_head"# onto the next patch:msgnum=$(($msgnum+1))-echo"$msgnum">"$dotest/msgnum"+echo"$msgnum">"$merge_dir/msgnum"} call_merge(){-cmt="$(cat"$dotest/cmt.$1")"-echo"$cmt">"$dotest/current"+cmt="$(cat"$merge_dir/cmt.$1")"+echo"$cmt">"$merge_dir/current"hd=$(gitrev-parse--verifyHEAD)cmt_name=$(gitsymbolic-refHEAD2>/dev/null||echoHEAD)-msgnum=$(cat"$dotest/msgnum")-end=$(cat"$dotest/end")+msgnum=$(cat"$merge_dir/msgnum")+end=$(cat"$merge_dir/end")evalGITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'-evalGITHEAD_$hd='$(cat "$dotest/onto_name")'+evalGITHEAD_$hd='$(cat "$merge_dir/onto_name")'exportGITHEAD_$cmtGITHEAD_$hdiftest-n"$GIT_QUIET"then
@@ -195,7 +196,7 @@ run_pre_rebase_hook () {fi}-test-f"$GIT_DIR"/rebase-apply/applying&&+test-f"$apply_dir"/applying&&die'It looks like git-am is in progress. Cannot rebase.' is_interactive"$@"&&execgit-rebase--interactive"$@"
@@ -210,7 +211,7 @@ doOK_TO_SKIP_PRE_REBASE=;;--continue)-test-d"$dotest"-o-d"$GIT_DIR"/rebase-apply||+test-d"$merge_dir"-o-d"$apply_dir"||die"No rebase in progress?"gitupdate-index--ignore-submodules--refresh&&
@@ -219,13 +220,13 @@ doecho"mark them as resolved using git add"exit1}-iftest-d"$dotest"+iftest-d"$merge_dir"then-prev_head=$(cat"$dotest/prev_head")-end=$(cat"$dotest/end")-msgnum=$(cat"$dotest/msgnum")-onto=$(cat"$dotest/onto")-GIT_QUIET=$(cat"$dotest/quiet")+prev_head=$(cat"$merge_dir/prev_head")+end=$(cat"$merge_dir/end")+msgnum=$(cat"$merge_dir/msgnum")+onto=$(cat"$merge_dir/onto")+GIT_QUIET=$(cat"$merge_dir/quiet")continue_mergewhiletest"$msgnum"-le"$end"do
@@ -235,28 +236,28 @@ dofinish_rb_mergeexitfi-head_name=$(cat"$GIT_DIR"/rebase-apply/head-name)&&-onto=$(cat"$GIT_DIR"/rebase-apply/onto)&&-orig_head=$(cat"$GIT_DIR"/rebase-apply/orig-head)&&-GIT_QUIET=$(cat"$GIT_DIR"/rebase-apply/quiet)+head_name=$(cat"$apply_dir"/head-name)&&+onto=$(cat"$apply_dir"/onto)&&+orig_head=$(cat"$apply_dir"/orig-head)&&+GIT_QUIET=$(cat"$apply_dir"/quiet)gitam--resolved--3way--resolvemsg="$RESOLVEMSG"&&move_to_original_branchexit;;--skip)-test-d"$dotest"-o-d"$GIT_DIR"/rebase-apply||+test-d"$merge_dir"-o-d"$apply_dir"||die"No rebase in progress?"gitreset--hardHEAD||exit$?-iftest-d"$dotest"+iftest-d"$merge_dir"thengitrerereclear-prev_head=$(cat"$dotest/prev_head")-end=$(cat"$dotest/end")-msgnum=$(cat"$dotest/msgnum")+prev_head=$(cat"$merge_dir/prev_head")+end=$(cat"$merge_dir/end")+msgnum=$(cat"$merge_dir/msgnum")msgnum=$(($msgnum+1))-onto=$(cat"$dotest/onto")-GIT_QUIET=$(cat"$dotest/quiet")+onto=$(cat"$merge_dir/onto")+GIT_QUIET=$(cat"$merge_dir/quiet")whiletest"$msgnum"-le"$end"docall_merge"$msgnum"
@@ -265,31 +266,31 @@ dofinish_rb_mergeexitfi-head_name=$(cat"$GIT_DIR"/rebase-apply/head-name)&&-onto=$(cat"$GIT_DIR"/rebase-apply/onto)&&-orig_head=$(cat"$GIT_DIR"/rebase-apply/orig-head)&&-GIT_QUIET=$(cat"$GIT_DIR"/rebase-apply/quiet)+head_name=$(cat"$apply_dir"/head-name)&&+onto=$(cat"$apply_dir"/onto)&&+orig_head=$(cat"$apply_dir"/orig-head)&&+GIT_QUIET=$(cat"$apply_dir"/quiet)gitam-3--skip--resolvemsg="$RESOLVEMSG"&&move_to_original_branchexit;;--abort)-test-d"$dotest"-o-d"$GIT_DIR"/rebase-apply||+test-d"$merge_dir"-o-d"$apply_dir"||die"No rebase in progress?"gitrerereclear-test-d"$dotest"||dotest="$GIT_DIR"/rebase-apply+test-d"$merge_dir"||merge_dir="$apply_dir"-head_name="$(cat"$dotest"/head-name)"&&+head_name="$(cat"$merge_dir"/head-name)"&&case"$head_name"inrefs/*)gitsymbolic-refHEAD$head_name||die"Could not move back to $head_name";;esac-gitreset--hard$(cat"$dotest/orig-head")-rm-r"$dotest"+gitreset--hard$(cat"$merge_dir/orig-head")+rm-r"$merge_dir"exit;;--onto)
@@ -388,31 +389,31 @@ test $# -gt 2 && usageiftest$#-eq0&&test-z"$rebase_root"then-test-d"$dotest"-o-d"$GIT_DIR"/rebase-apply||usage-test-d"$dotest"-o-f"$GIT_DIR"/rebase-apply/rebasing&&+test-d"$merge_dir"-o-d"$apply_dir"||usage+test-d"$merge_dir"-o-f"$apply_dir"/rebasing&&die'A rebase is in progress, try --continue, --skip or --abort.'fi-# Make sure we do not have $GIT_DIR/rebase-apply+# Make sure we do not have $apply_dir or $merge_diriftest-z"$do_merge"then-ifmkdir"$GIT_DIR"/rebase-apply2>/dev/null+ifmkdir"$apply_dir"2>/dev/nullthen-rmdir"$GIT_DIR"/rebase-apply+rmdir"$apply_dir"elseecho>&2' ItseemsthatIcannotcreatearebase-applydirectory,and Iwonderifyouareinthemiddleofpatchapplicationoranother rebase.Ifthatisnotthecase,please-rm-fr'"$GIT_DIR"'/rebase-apply+rm-fr'"$apply_dir"' andrunmeagain.Iamstoppingincaseyoustillhavesomething valuablethere.'exit1fielse-iftest-d"$dotest"+iftest-d"$merge_dir"then-die"previous rebase directory $dotest still exists."\+die"previous rebase directory $merge_dir still exists."\'Try git rebase (--continue | --abort | --skip)'fifi
@@ -560,35 +561,35 @@ thengitam$git_am_opt--rebasing--resolvemsg="$RESOLVEMSG"&&move_to_original_branchret=$?-test0!=$ret-a-d"$GIT_DIR"/rebase-apply&&-echo$head_name>"$GIT_DIR"/rebase-apply/head-name&&-echo$onto>"$GIT_DIR"/rebase-apply/onto&&-echo$orig_head>"$GIT_DIR"/rebase-apply/orig-head&&-echo"$GIT_QUIET">"$GIT_DIR"/rebase-apply/quiet+test0!=$ret-a-d"$apply_dir"&&+echo$head_name>"$apply_dir/head-name"&&+echo$onto>"$apply_dir/onto"&&+echo$orig_head>"$apply_dir/orig-head"&&+echo"$GIT_QUIET">"$apply_dir/quiet"exit$retfi# start doing a rebase with git-merge# this is rename-aware if the recursive (default) strategy is used-mkdir-p"$dotest"-echo"$onto">"$dotest/onto"-echo"$onto_name">"$dotest/onto_name"+mkdir-p"$merge_dir"+echo"$onto">"$merge_dir/onto"+echo"$onto_name">"$merge_dir/onto_name"prev_head=$orig_head-echo"$prev_head">"$dotest/prev_head"-echo"$orig_head">"$dotest/orig-head"-echo"$head_name">"$dotest/head-name"-echo"$GIT_QUIET">"$dotest/quiet"+echo"$prev_head">"$merge_dir/prev_head"+echo"$orig_head">"$merge_dir/orig-head"+echo"$head_name">"$merge_dir/head-name"+echo"$GIT_QUIET">"$merge_dir/quiet"msgnum=0forcmtin`gitrev-list--reverse--no-merges"$revisions"`domsgnum=$(($msgnum+1))-echo"$cmt">"$dotest/cmt.$msgnum"+echo"$cmt">"$merge_dir/cmt.$msgnum"done-echo1>"$dotest/msgnum"-echo$msgnum>"$dotest/end"+echo1>"$merge_dir/msgnum"+echo$msgnum>"$merge_dir/end"end=$msgnummsgnum=1
From: Thomas Rast <hidden> Date: 2016-06-15 22:50:18
Martin von Zweigbergk wrote:
quoted hunk
@@ -168,11 +168,6 @@ pick_one () { output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1" test -d "$REWRITTEN" && pick_one_preserving_merges "$@" && return- if test -n "$rebase_root"- then- output git cherry-pick "$@"- return- fi output git cherry-pick $ff "$@" }
[...]
While factoring out the state writing code a few patches back, I went
through each of the pieces of state that was written. I was a bit
hesitant to include this patch since I'm not quite sure why the code
was introduced, but I thought I would include it anyway to hear what
you have to say.
There used to be bug when using --ff when rebasing a root commit. This
was fixed in 6355e50 (builtin/revert.c: don't dereference a NULL
pointer, 2010-09-27). Could this have been the reason for the check?
Thomas, do you remember?
I think this just ended up being such a strange test because of the
following hunk in 8e75abf (rebase -i: use new --ff cherry-pick option,
2010-03-06):
@@ -232,16 +232,7 @@ pick_one () { output git cherry-pick "$@" return fi- parent_sha1=$(git rev-parse --verify $sha1^) ||- die "Could not get the parent of $sha1"- current_sha1=$(git rev-parse --verify HEAD)- if test -z "$no_ff" && test "$current_sha1" = "$parent_sha1"- then- output git reset --hard $sha1- output warn Fast-forward to $(git rev-parse --short $sha1)- else- output git cherry-pick "$@"- fi+ output git cherry-pick $ff "$@" }
Hmpf... After a rebasing merge to junio/next:
-- snip --
[...]
Applying: rebase -i: support --stat
fatal: sha1 information is lacking or useless (git-rebase.sh).
Repository lacks necessary blobs to fall back on 3-way merge.
Cannot fall back to three-way merge.
[...]
-- snap --
Is this supposed to apply on top of junio/master, junio/next, junio/maint?
Ciao,
Dscho
Hmpf... After a rebasing merge to junio/next:
-- snip --
[...]
Applying: rebase -i: support --stat
fatal: sha1 information is lacking or useless (git-rebase.sh).
Repository lacks necessary blobs to fall back on 3-way merge.
Cannot fall back to three-way merge.
[...]
-- snap --
Is this supposed to apply on top of junio/master, junio/next, junio/maint?
It is supposed to apply on top of junio/master. I tried exporting the
recevied emails using Alpine. This is the first time I do this, but I
managed to export them to one big file. I then applied it using 'git
am' onto a new branch created from junio/master and it was
successful. I'm very surprised that patch 16 failed for you if the
first 15 patches applied correctly.
I'm not sure what to use the hashes in the beginning of your mail for,
but I have verified that they match the hashes of git-rebase.sh before
and after patch 16 (in both my original branch and in the temporary
branch where I ran 'git am' on my own emails).
Regards,
Martin
From: Junio C Hamano <hidden> Date: 2016-06-15 22:50:18
Martin von Zweigbergk [off-list ref] writes:
Currently, the existence of rebase-merge/ is tested with 'test -d',
while the existence of rebase-apply/ is tested by creating the
directory and then deleting it again. Any good reason for this?
I don't recall how the merge side reached the current shape of the code,
but I think the rebase-apply one was that we wanted to make sure not only
we don't have a directory but also we actually _can_ create one. If
somebody had a bad permission set, "test -d" wouldn't help us much. We
would fail later and error diagnosis codepath should do the right thing
anyway, so it is not a correctness issue, but is more about attempting to
notice an error early rather than late.
It used to be safe to call this without head_name and friends set, because
the function took care of reading these itself. Nobody calls this without
head_name set anymore?
I am not complaining nor suggesting to add an unnecessary "read_state"
here only to slow things down---I am making sure that you removed this
because you know it is unnecessary.
quoted hunk
@@ -220,13 +232,9 @@ do echo "mark them as resolved using git add" exit 1 }+ read_state if test -d "$merge_dir" then- prev_head=$(cat "$merge_dir/prev_head")- end=$(cat "$merge_dir/end")- msgnum=$(cat "$merge_dir/msgnum")- onto=$(cat "$merge_dir/onto")- GIT_QUIET=$(cat "$merge_dir/quiet")
Even though this patch may make the code shorter, it starts to read
head_name and orig_head that we previously did not open and change the
values of variables with what are read from them. Does this change affect
the behaviour in any way (either in performance or in correctness)?
Earlier move-to-original-branch was Ok to be called without head_name, and
the old code here read from the file anyway, so it didn't matter, but now
it seems that the first check and assignment you removed from the function
may matter because this caller does not even read from head_name. Are you
sure about this change?
quoted hunk
@@ -279,18 +275,15 @@ do die "No rebase in progress?" git rerere clear-- test -d "$merge_dir" || merge_dir="$apply_dir"
My heartbeat skipped when I first saw this. Thanks to the previous
commit, it was exposed that somebody reused $dotest that was only to be
used when using merge machinery because the things left to be done in this
codepath are common between the merge and apply, which is kind of sloppy,
but that sloppiness is now gone ;-).
Are there places that read from individual files for states left after
this patch, or read_state is the only interface to get to the states? If
the latter that would be a great news, and also would suggest that we may
want to have a corresponding write_state function (and we may even want to
make the state into a single file to reduce I/O---but that is a separate
issue that can be done at the very end of the series if it turns out to be
beneficial).
Of course it is fine if introduction of read_state is an attempt to catch
most common cases, but it would reduce chances of mistake if the coverage
were 100% (as opposed to 99.9%) hence this question.
From: Junio C Hamano <hidden> Date: 2016-06-15 22:50:18
If this were just "s/dotest/merge_dir/g" and the same for rebase-apply, I
would have to say it is long overdue ;-)
I read the patch and didn't spot any glaring mistake, but I wasn't being
as careful as I usually am.
Thanks.
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
On Tue, 28 Dec 2010, Junio C Hamano wrote:
Martin von Zweigbergk [off-list ref] writes:
quoted
Currently, the existence of rebase-merge/ is tested with 'test -d',
while the existence of rebase-apply/ is tested by creating the
directory and then deleting it again. Any good reason for this?
I don't recall how the merge side reached the current shape of the code,
but I think the rebase-apply one was that we wanted to make sure not only
we don't have a directory but also we actually _can_ create one. If
somebody had a bad permission set, "test -d" wouldn't help us much. We
would fail later and error diagnosis codepath should do the right thing
anyway, so it is not a correctness issue, but is more about attempting to
notice an error early rather than late.
Yeah, I was wondering if that might have been the reason. Why would
anyone set such permissions on .git (keep in mind that I am no
Linux/Unix expert)?
I saw that the code was introduced [1] when the directory was called
.dotest and I believe this directory was created at the top level
(i.e. a sibling to .git). Could it be that it was reasonable for the
user to set such permissions back then (on the top level dir), but not
any longer (on the .git dir)?
Either way, if it is good to have the that check for rebase-apply/,
wouldn't it be good to have for rebase-merge/ as well?
/Martin
[1] 7f4bd5d (rebase: one safety net, one bugfix and one optimization.,
2005-11-28)
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
On Tue, 28 Dec 2010, Junio C Hamano wrote:
If this were just "s/dotest/merge_dir/g" and the same for rebase-apply, I
would have to say it is long overdue ;-)
Yes, that should be all!
Well, to be precise, in the "@@ -560,35 +561,35 @@ then" hunk, I also
moved the quotes to contain the file name as was done for
rebase-merge. I redid the search/replace just to double check.
It used to be safe to call this without head_name and friends set, because
the function took care of reading these itself. Nobody calls this without
head_name set anymore?
I am not complaining nor suggesting to add an unnecessary "read_state"
here only to slow things down---I am making sure that you removed this
because you know it is unnecessary.
Correct. It used to be called without head_name set from
finish_rb_merge, which would in turn be called from the --continue and
--skip arms. onto would already have been set in these cases, but
would then be re-read.
quoted
@@ -220,13 +232,9 @@ do echo "mark them as resolved using git add" exit 1 }+ read_state if test -d "$merge_dir" then- prev_head=$(cat "$merge_dir/prev_head")- end=$(cat "$merge_dir/end")- msgnum=$(cat "$merge_dir/msgnum")- onto=$(cat "$merge_dir/onto")- GIT_QUIET=$(cat "$merge_dir/quiet")
Even though this patch may make the code shorter, it starts to read
head_name and orig_head that we previously did not open and change the
values of variables with what are read from them. Does this change affect
the behaviour in any way (either in performance or in correctness)?
True. Previously, head_name and orig_head were lazily read only when
the rebase had been finished (in the finish_rb_merge, as I mentioned
above). Now these values are read unnecessarily when the rebase is
resumed, but a later patch fails. The am-based rebase is not affacted
by this patch as it already read head_name and orig_head eagerly.
Good point about the correctness. I looked into the correctness issue
arising if a file could not be found and I think I concluded that all
of the files would always be written (do we need to care about the
case where a user deletes e.g. .git/rebase-apply/onto?). However, I
did not think about the possibility of overwriting variables. It seems
fine, though, as neither continue_merge nor call_merge uses either of
these variables.
Regarding performance, I would say there is definitely a cost
associated with this patch. How big this cost is, though, I don't dare
to speculate. I will leave that up to the rest of you.
It should be noted that read_state is only called when a rebase is
resumed with --continue or --skip, or when it is aborted. There are no
changes to the code in the call_merge-continue_merge loop.
The performance hit is probably biggest in the --abort case, which
previously only read head_name and orig_head. It now ends up reading
_at least_ two more values.
Earlier move-to-original-branch was Ok to be called without head_name, and
the old code here read from the file anyway, so it didn't matter, but now
it seems that the first check and assignment you removed from the function
may matter because this caller does not even read from head_name. Are you
sure about this change?
If I understand your question correctly, then yes, it is ok, because
of the previous hunk that calls read_state. That call is made
before/outside the if block for merge-based rebase, so the variables
are already set when this code is reached.
quoted
@@ -279,18 +275,15 @@ do die "No rebase in progress?" git rerere clear-- test -d "$merge_dir" || merge_dir="$apply_dir"
My heartbeat skipped when I first saw this. Thanks to the previous
commit, it was exposed that somebody reused $dotest that was only to be
used when using merge machinery because the things left to be done in this
codepath are common between the merge and apply, which is kind of sloppy,
but that sloppiness is now gone ;-).
Are there places that read from individual files for states left after
this patch, or read_state is the only interface to get to the states? If
the latter that would be a great news, and also would suggest that we may
want to have a corresponding write_state function (and we may even want to
make the state into a single file to reduce I/O---but that is a separate
issue that can be done at the very end of the series if it turns out to be
beneficial).
There are still a few other places where state is read, mainly in
call_merge. It reads things that vary from iteration to iteration,
such as a counter. I forgot to say in the commit message, but I tried
to extract only the code that reads the initial state.
The write_state function actually is there, but it comes pretty late,
in patch 24. I don't remember why I added it so much later. I could
possibly move it closer to the beginning of this series.
Of course it is fine if introduction of read_state is an attempt to catch
most common cases, but it would reduce chances of mistake if the coverage
were 100% (as opposed to 99.9%) hence this question.
Do you mean if all the state was read in the read_state function? I
should say that the pieces of state that are read in read_state are
not read anywhere else. But overall, the coverage is more like 60% or
so.
Thanks for a thorough review. Many of these things should have been in
the commit message. I need to get better at writing those...
Thanks,
Martin
I'd prefer to dispatch to the final rebase type using
. git-rebase--$type
This way, you can avoid to export the huge list of helper variables and the
function. (And it might be faster by a millisecond - or a few dozens on
Windows.)
-- Hannes
It seems like it isn't. What is a good way to check?
quoted
+ test "$type" != am && exec git-rebase--$type
I'd prefer to dispatch to the final rebase type using
. git-rebase--$type
This way, you can avoid to export the huge list of helper variables and the
function. (And it might be faster by a millisecond - or a few dozens on
Windows.)
Makes a lot of sense. Will change. Why didn't I do that from the
beginning?
Thanks,
Martin
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:18
On Tue, 28 Dec 2010, Thomas Rast wrote:
quoted hunk
Martin von Zweigbergk wrote:
quoted
@@ -168,11 +168,6 @@ pick_one () { output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1" test -d "$REWRITTEN" && pick_one_preserving_merges "$@" && return- if test -n "$rebase_root"- then- output git cherry-pick "$@"- return- fi output git cherry-pick $ff "$@" }
[...]
quoted
While factoring out the state writing code a few patches back, I went
through each of the pieces of state that was written. I was a bit
hesitant to include this patch since I'm not quite sure why the code
was introduced, but I thought I would include it anyway to hear what
you have to say.
There used to be bug when using --ff when rebasing a root commit. This
was fixed in 6355e50 (builtin/revert.c: don't dereference a NULL
pointer, 2010-09-27). Could this have been the reason for the check?
Thomas, do you remember?
I think this just ended up being such a strange test because of the
following hunk in 8e75abf (rebase -i: use new --ff cherry-pick option,
2010-03-06):
@@ -232,16 +232,7 @@ pick_one () { output git cherry-pick "$@" return fi- parent_sha1=$(git rev-parse --verify $sha1^) ||- die "Could not get the parent of $sha1"- current_sha1=$(git rev-parse --verify HEAD)- if test -z "$no_ff" && test "$current_sha1" = "$parent_sha1"- then- output git reset --hard $sha1- output warn Fast-forward to $(git rev-parse --short $sha1)- else- output git cherry-pick "$@"- fi+ output git cherry-pick $ff "$@" }
--
Yes, I saw that one as well, so it would probably have made more sense
to ask Christian instead (the author of 8e75abf). So do you remember,
Christian?
Anyway, thanks for your input, Thomas. That makes me feel a little
less worried about this patch.
/Martin
From: Christian Couder <hidden> Date: 2016-06-15 22:50:19
Hi,
On Wed, Dec 29, 2010 at 11:31 PM, Martin von Zweigbergk
[off-list ref] wrote:
On Tue, 28 Dec 2010, Thomas Rast wrote:
quoted
Martin von Zweigbergk wrote:
quoted
@@ -168,11 +168,6 @@ pick_one () {
output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
test -d "$REWRITTEN" &&
pick_one_preserving_merges "$@" && return
- if test -n "$rebase_root"
- then
- output git cherry-pick "$@"
- return
- fi
output git cherry-pick $ff "$@"
}
[...]
quoted
While factoring out the state writing code a few patches back, I went
through each of the pieces of state that was written. I was a bit
hesitant to include this patch since I'm not quite sure why the code
was introduced, but I thought I would include it anyway to hear what
you have to say.
There used to be bug when using --ff when rebasing a root commit. This
was fixed in 6355e50 (builtin/revert.c: don't dereference a NULL
pointer, 2010-09-27). Could this have been the reason for the check?
Thomas, do you remember?
I think this just ended up being such a strange test because of the
following hunk in 8e75abf (rebase -i: use new --ff cherry-pick option,
2010-03-06):
@@ -232,16 +232,7 @@ pick_one () {
output git cherry-pick "$@"
return
fi
- parent_sha1=$(git rev-parse --verify $sha1^) ||
- die "Could not get the parent of $sha1"
- current_sha1=$(git rev-parse --verify HEAD)
- if test -z "$no_ff" && test "$current_sha1" = "$parent_sha1"
- then
- output git reset --hard $sha1
- output warn Fast-forward to $(git rev-parse --short $sha1)
- else
- output git cherry-pick "$@"
- fi
+ output git cherry-pick $ff "$@"
}
--
Yes, I saw that one as well, so it would probably have made more sense
to ask Christian instead (the author of 8e75abf). So do you remember,
Christian?
Yeah, I must say that I did not try to understand why there was a
special case for $rebase_root above the code I was changing.
Perhaps I should have, and I would probably have sent a patch like yours...
Anyway, thanks for your input, Thomas. That makes me feel a little
less worried about this patch.
From: Thomas Rast <hidden> Date: 2016-06-15 22:50:19
Martin von Zweigbergk wrote:
On Wed, 29 Dec 2010, Johannes Sixt wrote:
quoted
Is export -f portable?
It seems like it isn't. What is a good way to check?
On my system I have POSIX docs for various commands, coming from the
'man-pages-posix' package. Maybe your distribution has those too?
Then you can simply run 'man 1p export' for the documentation.
Anything that is documented there should be safe (except on Windows
maybe).
--
Thomas Rast
trast@{inf,student}.ethz.ch
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:19
On Fri, 31 Dec 2010, Thomas Rast wrote:
Martin von Zweigbergk wrote:
quoted
On Wed, 29 Dec 2010, Johannes Sixt wrote:
quoted
Is export -f portable?
It seems like it isn't. What is a good way to check?
On my system I have POSIX docs for various commands, coming from the
'man-pages-posix' package. Maybe your distribution has those too?
Then you can simply run 'man 1p export' for the documentation.
Anything that is documented there should be safe (except on Windows
maybe).
Thanks. I'm running Debian and I just installed the package from
non-free. Thanks for the hint on the '1p' syntax as well.
/Martin
From: Thomas Rast <hidden> Date: 2016-06-15 22:50:19
Martin von Zweigbergk wrote:
Use the same names for variables that git-rebase--interactive.sh will
soon inherit from git-rebase.sh.
AFAICS this is partly about spelling the variables in lowercase
instead of all-caps.
Wouldn't it be nicer to simply downcase *all* variables, so that the
end result has a consistent coding style?
-# $UPSTREAM. They are not necessarily rewritten, but their children
+# $upstream. They are not necessarily rewritten, but their children
From: Thomas Rast <hidden> Date: 2016-06-15 22:50:19
Martin von Zweigbergk wrote:
Note that non-interactive rebase stores the sha1 of the original head
in a file called orig-head, while interactive rebase stores it in a
file called head.
[...]
+ if test "$type" = interactive
+ then
+ echo "$orig_head" > "$state_dir"/head
+ else
+ echo "$orig_head" > "$state_dir"/orig-head
+ fi &&
Do we have to cater to the use-case where the user starts a rebase,
downgrades at a conflict, and then continues?
If not, you could read 'orig-head' first and fall back to 'head', only
writing 'orig-head' in the state saving independent of the mode. That
would give us the chance of removing the redundancy at some point.
--
Thomas Rast
trast@{inf,student}.ethz.ch
From: Thomas Rast <hidden> Date: 2016-06-15 22:50:19
Martin von Zweigbergk wrote:
How to add support for strategy options to interactive rebase?
AFAICS rebase -i currently only uses the strategy when dealing with
multiple parents, i.e., in --preserve-merges mode. I think
git-cherry-pick needs to learn about the -s and -X options, and then
it'll be a simple matter of passing them along.
--
Thomas Rast
trast@{inf,student}.ethz.ch
From: Thomas Rast <hidden> Date: 2016-06-15 22:50:19
Martin von Zweigbergk wrote:
For the past two months, I have been working on refactoring the rebase
code. See [1] for background information. I have been trying to polish
the patch set for some time, but now I don't think I will get much
further without your help.
Thanks a lot for undertaking this effort! I just finished looking
through the entire series, and it all seems sane to me. Apart from
j6t's reply I think we're mostly nit-picking or agreeing with you, and
this is the first iteration!
--
Thomas Rast
trast@{inf,student}.ethz.ch
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:20
On Tue, 4 Jan 2011, Thomas Rast wrote:
Martin von Zweigbergk wrote:
quoted
Use the same names for variables that git-rebase--interactive.sh will
soon inherit from git-rebase.sh.
AFAICS this is partly about spelling the variables in lowercase
instead of all-caps.
Wouldn't it be nicer to simply downcase *all* variables, so that the
end result has a consistent coding style?
Yes, it would :-). I was just being conservative by trying not to
touch code that I didn't have to touch. I'll rename the remaining
variables in the next iteration.
Thanks,
Martin
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:20
On Tue, 4 Jan 2011, Thomas Rast wrote:
Martin von Zweigbergk wrote:
quoted
Note that non-interactive rebase stores the sha1 of the original head
in a file called orig-head, while interactive rebase stores it in a
file called head.
[...]
quoted
+ if test "$type" = interactive
+ then
+ echo "$orig_head" > "$state_dir"/head
+ else
+ echo "$orig_head" > "$state_dir"/orig-head
+ fi &&
Do we have to cater to the use-case where the user starts a rebase,
downgrades at a conflict, and then continues?
I'll let Junio answer that.
If not, you could read 'orig-head' first and fall back to 'head', only
writing 'orig-head' in the state saving independent of the mode. That
would give us the chance of removing the redundancy at some point.
Makes sense. Given that the answer to the previous question is a "no",
I'll change this as well in the next iteration.
/Martin
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:20
On Tue, 4 Jan 2011, Thomas Rast wrote:
Martin von Zweigbergk wrote:
quoted
How to add support for strategy options to interactive rebase?
AFAICS rebase -i currently only uses the strategy when dealing with
multiple parents, i.e., in --preserve-merges mode. I think
git-cherry-pick needs to learn about the -s and -X options, and then
it'll be a simple matter of passing them along.
I just saw that Jonathan has actually implemented that support in
git-cherry-pick. It is currently in pu.
I asked just because the merge strategy is currently passed to the
call to 'git merge' in git-rebase--interactive.sh (when dealing with
multiple parents, as you said), so it seems like it would make sense
to pass any merge options there as well.
Come to think of it, doesn't the merge option when passed to 'git
rebase -i' mean something quite different compared to when it is
passed to 'git rebase -m'? For interactive rebase, the 'ours' side
refers to the upstream, but in the case of merge-based rebase, it
refers to one branch in the branch-to-be-rebased, no? In that case,
should the merge strategy even be passed to 'git merge' when dealing
with multiple parents? Is it likely that one would want to use the
same strategy for both things? Am I just not thinking straight?
Some history:
The command line option '-s' was there from the inception of
interactive rebase in 1b1dce4 (Teach rebase an interactive mode,
2007-06-25) and back then it was passed to git-cherry-pick, which just
ignored it.
Since f09c9b8 (Teach rebase -i about --preserve-merges, 2007-06-25),
the strategy has been passed to git-merge as well.
Since 2a9c53e (git-rebase--interactive.sh: Don't pass a strategy to
git-cherry-pick., 2007-10-31), the strategy has only been passed to
git-merge, because it was ignored by git-cherry-pick.
Anyway, I'll leave any changes related to this outside of the current
series.
/Martin
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:20
On Tue, 4 Jan 2011, Thomas Rast wrote:
Martin von Zweigbergk wrote:
quoted
For the past two months, I have been working on refactoring the rebase
code. See [1] for background information. I have been trying to polish
the patch set for some time, but now I don't think I will get much
further without your help.
Thanks a lot for undertaking this effort! I just finished looking
through the entire series, and it all seems sane to me. Apart from
j6t's reply I think we're mostly nit-picking or agreeing with you, and
this is the first iteration!
Thanks. And thanks a lot for taking the time to review it!
/Martin
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:24
On Tue, 28 Dec 2010, Martin von Zweigbergk wrote:
On Tue, 28 Dec 2010, Junio C Hamano wrote:
quoted
Martin von Zweigbergk [off-list ref] writes:
quoted
Currently, the existence of rebase-merge/ is tested with 'test -d',
while the existence of rebase-apply/ is tested by creating the
directory and then deleting it again. Any good reason for this?
I don't recall how the merge side reached the current shape of the code,
but I think the rebase-apply one was that we wanted to make sure not only
we don't have a directory but also we actually _can_ create one. If
somebody had a bad permission set, "test -d" wouldn't help us much. We
would fail later and error diagnosis codepath should do the right thing
anyway, so it is not a correctness issue, but is more about attempting to
notice an error early rather than late.
Yeah, I was wondering if that might have been the reason. Why would
anyone set such permissions on .git (keep in mind that I am no
Linux/Unix expert)?
I saw that the code was introduced [1] when the directory was called
.dotest and I believe this directory was created at the top level
(i.e. a sibling to .git). Could it be that it was reasonable for the
user to set such permissions back then (on the top level dir), but not
any longer (on the .git dir)?
Either way, if it is good to have the that check for rebase-apply/,
wouldn't it be good to have for rebase-merge/ as well?
/Martin
[1] 7f4bd5d (rebase: one safety net, one bugfix and one optimization.,
2005-11-28)
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:30
Changes since the first round:
As suggested by Johannes Sixt, source git-rebase--interactive.sh and
friends instead of executing them.
As suggested by Thomas Rast, downcase all variables for consitency.
Based on current master, including Jeff's two patches to rebase.
There are also a few other minor changes, but see the notes in each
patch for more information.
Martin von Zweigbergk (31):
rebase: clearer names for directory variables
rebase: refactor reading of state
rebase: read state outside loop
rebase: remove unused rebase state 'prev_head'
rebase: improve detection of rebase in progress
rebase: act on command line outside parsing loop
rebase: stricter check of standalone sub command
rebase: align variable names
rebase: align variable content
rebase: factor out command line option processing
rebase -i: remove now unnecessary directory checks
rebase: reorder validation steps
rebase: factor out reference parsing
rebase: factor out clean work tree check
rebase: factor out call to pre-rebase hook
rebase -i: support --stat
rebase: remove $branch as synonym for $orig_head
rebase: extract merge code to new source file
rebase: extract am code to new source file
rebase: show consistent conflict resolution hint
rebase -i: align variable names
rebase: make -v a tiny bit more verbose
rebase: factor out sub command handling
rebase: extract code for writing basic state
rebase: remember verbose option
rebase: remember strategy and strategy options
rebase -m: remember allow_rerere_autoupdate option
rebase -m: don't print exit code 2 when merge fails
git-rebase--am: remove unnecessary --3way option
rebase -i: don't read unused variable preserve_merges
rebase -i: remove unnecessary state rebase-root
.gitignore | 2 +
Makefile | 2 +
git-rebase--am.sh | 30 ++
git-rebase--interactive.sh | 751 +++++++++++++++----------------------------
git-rebase--merge.sh | 151 +++++++++
git-rebase.sh | 482 +++++++++++-----------------
t/t3403-rebase-skip.sh | 5 +
t/t3407-rebase-abort.sh | 10 +
t/t3418-rebase-continue.sh | 55 ++++
9 files changed, 707 insertions(+), 781 deletions(-)
create mode 100644 git-rebase--am.sh
create mode 100644 git-rebase--merge.sh
--
1.7.4.rc2.33.g8a14f
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:30
Instead of using the old variable name 'dotest' for
"$GIT_DIR"/rebase-merge and no variable for "$GIT_DIR"/rebase-apply,
introduce two variables 'merge_dir' and 'apply_dir' for these paths.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase.sh | 141 +++++++++++++++++++++++++++++----------------------------
1 files changed, 71 insertions(+), 70 deletions(-)
@@ -58,7 +59,7 @@ allow_rerere_autoupdate= continue_merge(){test-n"$prev_head"||die"prev_head must be defined"-test-d"$dotest"||die"$dotest directory does not exist"+test-d"$merge_dir"||die"$merge_dir directory does not exist"unmerged=$(gitls-files-u)iftest-n"$unmerged"
@@ -93,22 +94,22 @@ continue_merge () {prev_head=`gitrev-parseHEAD^0`# save the resulting commit so we can read-tree on it later-echo"$prev_head">"$dotest/prev_head"+echo"$prev_head">"$merge_dir/prev_head"# onto the next patch:msgnum=$(($msgnum+1))-echo"$msgnum">"$dotest/msgnum"+echo"$msgnum">"$merge_dir/msgnum"} call_merge(){-cmt="$(cat"$dotest/cmt.$1")"-echo"$cmt">"$dotest/current"+cmt="$(cat"$merge_dir/cmt.$1")"+echo"$cmt">"$merge_dir/current"hd=$(gitrev-parse--verifyHEAD)cmt_name=$(gitsymbolic-refHEAD2>/dev/null||echoHEAD)-msgnum=$(cat"$dotest/msgnum")-end=$(cat"$dotest/end")+msgnum=$(cat"$merge_dir/msgnum")+end=$(cat"$merge_dir/end")evalGITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'-evalGITHEAD_$hd='$(cat "$dotest/onto_name")'+evalGITHEAD_$hd='$(cat "$merge_dir/onto_name")'exportGITHEAD_$cmtGITHEAD_$hdiftest-n"$GIT_QUIET"then
@@ -195,7 +196,7 @@ run_pre_rebase_hook () {fi}-test-f"$GIT_DIR"/rebase-apply/applying&&+test-f"$apply_dir"/applying&&die'It looks like git-am is in progress. Cannot rebase.' is_interactive"$@"&&execgit-rebase--interactive"$@"
@@ -210,7 +211,7 @@ doOK_TO_SKIP_PRE_REBASE=;;--continue)-test-d"$dotest"-o-d"$GIT_DIR"/rebase-apply||+test-d"$merge_dir"-o-d"$apply_dir"||die"No rebase in progress?"gitupdate-index--ignore-submodules--refresh&&
@@ -219,13 +220,13 @@ doecho"mark them as resolved using git add"exit1}-iftest-d"$dotest"+iftest-d"$merge_dir"then-prev_head=$(cat"$dotest/prev_head")-end=$(cat"$dotest/end")-msgnum=$(cat"$dotest/msgnum")-onto=$(cat"$dotest/onto")-GIT_QUIET=$(cat"$dotest/quiet")+prev_head=$(cat"$merge_dir/prev_head")+end=$(cat"$merge_dir/end")+msgnum=$(cat"$merge_dir/msgnum")+onto=$(cat"$merge_dir/onto")+GIT_QUIET=$(cat"$merge_dir/quiet")continue_mergewhiletest"$msgnum"-le"$end"do
@@ -235,28 +236,28 @@ dofinish_rb_mergeexitfi-head_name=$(cat"$GIT_DIR"/rebase-apply/head-name)&&-onto=$(cat"$GIT_DIR"/rebase-apply/onto)&&-orig_head=$(cat"$GIT_DIR"/rebase-apply/orig-head)&&-GIT_QUIET=$(cat"$GIT_DIR"/rebase-apply/quiet)+head_name=$(cat"$apply_dir"/head-name)&&+onto=$(cat"$apply_dir"/onto)&&+orig_head=$(cat"$apply_dir"/orig-head)&&+GIT_QUIET=$(cat"$apply_dir"/quiet)gitam--resolved--3way--resolvemsg="$RESOLVEMSG"&&move_to_original_branchexit;;--skip)-test-d"$dotest"-o-d"$GIT_DIR"/rebase-apply||+test-d"$merge_dir"-o-d"$apply_dir"||die"No rebase in progress?"gitreset--hardHEAD||exit$?-iftest-d"$dotest"+iftest-d"$merge_dir"thengitrerereclear-prev_head=$(cat"$dotest/prev_head")-end=$(cat"$dotest/end")-msgnum=$(cat"$dotest/msgnum")+prev_head=$(cat"$merge_dir/prev_head")+end=$(cat"$merge_dir/end")+msgnum=$(cat"$merge_dir/msgnum")msgnum=$(($msgnum+1))-onto=$(cat"$dotest/onto")-GIT_QUIET=$(cat"$dotest/quiet")+onto=$(cat"$merge_dir/onto")+GIT_QUIET=$(cat"$merge_dir/quiet")whiletest"$msgnum"-le"$end"docall_merge"$msgnum"
@@ -265,31 +266,31 @@ dofinish_rb_mergeexitfi-head_name=$(cat"$GIT_DIR"/rebase-apply/head-name)&&-onto=$(cat"$GIT_DIR"/rebase-apply/onto)&&-orig_head=$(cat"$GIT_DIR"/rebase-apply/orig-head)&&-GIT_QUIET=$(cat"$GIT_DIR"/rebase-apply/quiet)+head_name=$(cat"$apply_dir"/head-name)&&+onto=$(cat"$apply_dir"/onto)&&+orig_head=$(cat"$apply_dir"/orig-head)&&+GIT_QUIET=$(cat"$apply_dir"/quiet)gitam-3--skip--resolvemsg="$RESOLVEMSG"&&move_to_original_branchexit;;--abort)-test-d"$dotest"-o-d"$GIT_DIR"/rebase-apply||+test-d"$merge_dir"-o-d"$apply_dir"||die"No rebase in progress?"gitrerereclear-test-d"$dotest"||dotest="$GIT_DIR"/rebase-apply+test-d"$merge_dir"||merge_dir="$apply_dir"-head_name="$(cat"$dotest"/head-name)"&&+head_name="$(cat"$merge_dir"/head-name)"&&case"$head_name"inrefs/*)gitsymbolic-refHEAD$head_name||die"Could not move back to $head_name";;esac-gitreset--hard$(cat"$dotest/orig-head")-rm-r"$dotest"+gitreset--hard$(cat"$merge_dir/orig-head")+rm-r"$merge_dir"exit;;--onto)
@@ -388,31 +389,31 @@ test $# -gt 2 && usageiftest$#-eq0&&test-z"$rebase_root"then-test-d"$dotest"-o-d"$GIT_DIR"/rebase-apply||usage-test-d"$dotest"-o-f"$GIT_DIR"/rebase-apply/rebasing&&+test-d"$merge_dir"-o-d"$apply_dir"||usage+test-d"$merge_dir"-o-f"$apply_dir"/rebasing&&die'A rebase is in progress, try --continue, --skip or --abort.'fi-# Make sure we do not have $GIT_DIR/rebase-apply+# Make sure we do not have $apply_dir or $merge_diriftest-z"$do_merge"then-ifmkdir"$GIT_DIR"/rebase-apply2>/dev/null+ifmkdir"$apply_dir"2>/dev/nullthen-rmdir"$GIT_DIR"/rebase-apply+rmdir"$apply_dir"elseecho>&2' ItseemsthatIcannotcreatearebase-applydirectory,and Iwonderifyouareinthemiddleofpatchapplicationoranother rebase.Ifthatisnotthecase,please-rm-fr'"$GIT_DIR"'/rebase-apply+rm-fr'"$apply_dir"' andrunmeagain.Iamstoppingincaseyoustillhavesomething valuablethere.'exit1fielse-iftest-d"$dotest"+iftest-d"$merge_dir"then-die"previous rebase directory $dotest still exists."\+die"previous rebase directory $merge_dir still exists."\'Try git rebase (--continue | --abort | --skip)'fifi
@@ -561,35 +562,35 @@ thengitam$git_am_opt--rebasing--resolvemsg="$RESOLVEMSG"&&move_to_original_branchret=$?-test0!=$ret-a-d"$GIT_DIR"/rebase-apply&&-echo$head_name>"$GIT_DIR"/rebase-apply/head-name&&-echo$onto>"$GIT_DIR"/rebase-apply/onto&&-echo$orig_head>"$GIT_DIR"/rebase-apply/orig-head&&-echo"$GIT_QUIET">"$GIT_DIR"/rebase-apply/quiet+test0!=$ret-a-d"$apply_dir"&&+echo$head_name>"$apply_dir/head-name"&&+echo$onto>"$apply_dir/onto"&&+echo$orig_head>"$apply_dir/orig-head"&&+echo"$GIT_QUIET">"$apply_dir/quiet"exit$retfi# start doing a rebase with git-merge# this is rename-aware if the recursive (default) strategy is used-mkdir-p"$dotest"-echo"$onto">"$dotest/onto"-echo"$onto_name">"$dotest/onto_name"+mkdir-p"$merge_dir"+echo"$onto">"$merge_dir/onto"+echo"$onto_name">"$merge_dir/onto_name"prev_head=$orig_head-echo"$prev_head">"$dotest/prev_head"-echo"$orig_head">"$dotest/orig-head"-echo"$head_name">"$dotest/head-name"-echo"$GIT_QUIET">"$dotest/quiet"+echo"$prev_head">"$merge_dir/prev_head"+echo"$orig_head">"$merge_dir/orig-head"+echo"$head_name">"$merge_dir/head-name"+echo"$GIT_QUIET">"$merge_dir/quiet"msgnum=0forcmtin`gitrev-list--reverse--no-merges"$revisions"`domsgnum=$(($msgnum+1))-echo"$cmt">"$dotest/cmt.$msgnum"+echo"$cmt">"$merge_dir/cmt.$msgnum"done-echo1>"$dotest/msgnum"-echo$msgnum>"$dotest/end"+echo1>"$merge_dir/msgnum"+echo$msgnum>"$merge_dir/end"end=$msgnummsgnum=1
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:30
The 'onto_name' state used in 'git rebase --merge' is currently read
once for each commit that need to be applied. It doesn't change
between each iteration, however, so it should be moved out of the
loop. This also makes the code more readable. Also remove the unused
variable 'end'.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase.sh | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:30
The state stored in $GIT_DIR/rebase-merge/prev_head was introduced in
58634db (rebase: Allow merge strategies to be used when rebasing,
2006-06-21), but it was never used and should therefore be removed.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase.sh | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
@@ -75,7 +74,6 @@ read_state () {} continue_merge(){-test-n"$prev_head"||die"prev_head must be defined"test-d"$merge_dir"||die"$merge_dir directory does not exist"unmerged=$(gitls-files-u)
@@ -109,10 +107,6 @@ continue_merge () {test-z"$GIT_QUIET"&&GIT_PAGER=''gitlog--format=%s-1"$cmt"-prev_head=`gitrev-parseHEAD^0`-# save the resulting commit so we can read-tree on it later-echo"$prev_head">"$merge_dir/prev_head"-# onto the next patch:msgnum=$(($msgnum+1))echo"$msgnum">"$merge_dir/msgnum"
@@ -568,8 +562,6 @@ fi mkdir-p"$merge_dir"echo"$onto_name">"$merge_dir/onto_name"-prev_head=$orig_head-echo"$prev_head">"$merge_dir/prev_head"echo"$head_name">"$merge_dir/head-name"echo"$onto">"$merge_dir/onto"echo"$orig_head">"$merge_dir/orig-head"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:30
Detect early on if a rebase is in progress and what type of rebase it
is (interactive, merge-based or am-based). This prepares for further
refactoring where am-based rebase will be dispatched to
git-rebase--am.sh and merge-based rebase will be dispatched to
git-rebase--merge.sh.
The idea is to use the same variables whether the type of rebase was
detected from rebase-apply/ or rebase-merge/ directories or from the
command line options. This will make the code more readable and will
later also make it easier to dispatch to the type-specific scripts.
Also show a consistent error message independent of the type of rebase
that was in progress and remove the obsolete wording about being in
the middle of a 'patch application', since that (an existing
"$GIT_DIR"/rebase-apply/applying) aborts 'git rebase' at an earlier
stage.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Currently, the existence of rebase-merge/ is tested with 'test -d',
while the existence of rebase-apply/ is tested by creating the
directory and then deleting it again. Any good reason for this?
There were some discussions on the above subject in the first round,
but nothing conclusive, so I have left it the way it was for now.
git-rebase.sh | 80 +++++++++++++++++++++++++++++---------------------------
1 files changed, 41 insertions(+), 39 deletions(-)
@@ -56,16 +56,19 @@ git_am_opt=rebase_root=force_rebase=allow_rerere_autoupdate=+# Non-empty if a rebase was in progress when 'git rebase' was invoked+in_progress=+# One of {am, merge, interactive}+type=+# One of {"$GIT_DIR"/rebase-apply, "$GIT_DIR"/rebase-merge}+state_dir= read_state(){-iftest-d"$merge_dir"+iftest"$type"=mergethen-state_dir="$merge_dir"-onto_name=$(cat"$merge_dir"/onto_name)&&-end=$(cat"$merge_dir"/end)&&-msgnum=$(cat"$merge_dir"/msgnum)-else-state_dir="$apply_dir"+onto_name=$(cat"$state_dir"/onto_name)&&+end=$(cat"$state_dir"/end)&&+msgnum=$(cat"$state_dir"/msgnum)fi&&head_name=$(cat"$state_dir"/head-name)&&onto=$(cat"$state_dir"/onto)&&
@@ -207,6 +210,23 @@ test -f "$apply_dir"/applying && is_interactive"$@"&&execgit-rebase--interactive"$@"+iftest-d"$apply_dir"+then+type=am+state_dir="$apply_dir"+eliftest-d"$merge_dir"+then+iftest-f"$merge_dir"/interactive+then+type=interactive+interactive_rebase=explicit+else+type=merge+fi+state_dir="$merge_dir"+fi+test-n"$type"&&in_progress=t+whiletest$#!=0docase"$1"in
@@ -217,8 +237,7 @@ doOK_TO_SKIP_PRE_REBASE=;;--continue)-test-d"$merge_dir"-o-d"$apply_dir"||-die"No rebase in progress?"+test-z"$in_progress"&&die"No rebase in progress?"gitupdate-index--ignore-submodules--refresh&&gitdiff-files--quiet--ignore-submodules||{
@@ -243,8 +262,7 @@ doexit;;--skip)-test-d"$merge_dir"-o-d"$apply_dir"||-die"No rebase in progress?"+test-z"$in_progress"&&die"No rebase in progress?"gitreset--hardHEAD||exit$?read_state
@@ -265,8 +283,7 @@ doexit;;--abort)-test-d"$merge_dir"-o-d"$apply_dir"||-die"No rebase in progress?"+test-z"$in_progress"&&die"No rebase in progress?"gitrerereclearread_state
@@ -374,37 +391,22 @@ dodonetest$#-gt2&&usage-iftest$#-eq0&&test-z"$rebase_root"+# Make sure no rebase is in progress+iftest-n"$in_progress"then-test-d"$merge_dir"-o-d"$apply_dir"||usage-test-d"$merge_dir"-o-f"$apply_dir"/rebasing&&-die'A rebase is in progress, try --continue, --skip or --abort.'-fi--# Make sure we do not have $apply_dir or $merge_dir-iftest-z"$do_merge"-then-ifmkdir"$apply_dir"2>/dev/null-then-rmdir"$apply_dir"-else-echo>&2'-ItseemsthatIcannotcreatearebase-applydirectory,and-Iwonderifyouareinthemiddleofpatchapplicationoranother-rebase.Ifthatisnotthecase,please-rm-fr'"$apply_dir"'+die'+Itseemsthatthereisalreadya'"${state_dir##*/}"'directory,and+Iwonderifyouareinthemiddleofanotherrebase.Ifthatisthe+case,pleasetry+gitrebase(--continue|--abort|--skip)+Ifthatisnotthecase,please+rm-fr'"$state_dir"' andrunmeagain.Iamstoppingincaseyoustillhavesomething valuablethere.'-exit1-fi-else-iftest-d"$merge_dir"-then-die"previous rebase directory $merge_dir still exists."\-'Try git rebase (--continue | --abort | --skip)'-fifi+test$#-eq0&&test-z"$rebase_root"&&usage+ require_clean_work_tree"rebase""Please commit or stash them."iftest-z"$rebase_root"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:30
To later be able to use the command line processing in git-rebase.sh
for both interactive and non-interactive rebases, move anything that
is specific to non-interactive rebase outside of the parsing
loop. Keep only parsing and validation of command line options in the
loop.
Signed-off-by: Martin von Zweigbergk <redacted>
---
May want to view this patch with --ignore-all-space.
git-rebase--interactive.sh | 300 ++++++++++++++++++++++----------------------
git-rebase.sh | 126 ++++++++++---------
2 files changed, 217 insertions(+), 209 deletions(-)
@@ -866,152 +866,158 @@ first and then run 'git rebase --continue' again.";;--)shift-test-z"$REBASE_ROOT"-a$#-ge1-a$#-le2||-test!-z"$REBASE_ROOT"-a$#-le1||usage-test-d"$DOTEST"&&-die"Interactive rebase already started"--gitvarGIT_COMMITTER_IDENT>/dev/null||-die"You need to set your committer info first"--iftest-z"$REBASE_ROOT"-then-UPSTREAM_ARG="$1"-UPSTREAM=$(gitrev-parse--verify"$1")||die"Invalid base"-test-z"$ONTO"&&ONTO=$UPSTREAM-shift-else-UPSTREAM=-UPSTREAM_ARG=--root-test-z"$ONTO"&&-die"You must specify --onto when using --root"-fi-run_pre_rebase_hook"$UPSTREAM_ARG""$@"--comment_for_reflogstart--require_clean_work_tree"rebase""Please commit or stash them."--iftest!-z"$1"-then-outputgitcheckout"$1"--||-die"Could not checkout $1"-fi+break+;;+esac+shift+done-HEAD=$(gitrev-parse--verifyHEAD)||die"No HEAD?"-mkdir"$DOTEST"||die"Could not create temporary $DOTEST"+test-z"$REBASE_ROOT"-a$#-ge1-a$#-le2||+test!-z"$REBASE_ROOT"-a$#-le1||usage+test-d"$DOTEST"&&+die"Interactive rebase already started"-:>"$DOTEST"/interactive||die"Could not mark as interactive"-gitsymbolic-refHEAD>"$DOTEST"/head-name2>/dev/null||-echo"detached HEAD">"$DOTEST"/head-name+gitvarGIT_COMMITTER_IDENT>/dev/null||+die"You need to set your committer info first"-echo$HEAD>"$DOTEST"/head-case"$REBASE_ROOT"in-'')-rm-f"$DOTEST"/rebase-root;;-*)-:>"$DOTEST"/rebase-root;;-esac-echo$ONTO>"$DOTEST"/onto-test-z"$STRATEGY"||echo"$STRATEGY">"$DOTEST"/strategy-testt="$VERBOSE"&&:>"$DOTEST"/verbose-iftestt="$PRESERVE_MERGES"-then-iftest-z"$REBASE_ROOT"-then-mkdir"$REWRITTEN"&&-forcin$(gitmerge-base--all$HEAD$UPSTREAM)-do-echo$ONTO>"$REWRITTEN"/$c||-die"Could not init rewritten commits"-done-else-mkdir"$REWRITTEN"&&-echo$ONTO>"$REWRITTEN"/root||-die"Could not init rewritten commits"-fi-# No cherry-pick because our first pass is to determine-# parents to rewrite and skipping dropped commits would-# prematurely end our probe-MERGES_OPTION=-first_after_upstream="$(gitrev-list--reverse--first-parent$UPSTREAM..$HEAD|head-n1)"-else-MERGES_OPTION="--no-merges --cherry-pick"-fi--SHORTHEAD=$(gitrev-parse--short$HEAD)-SHORTONTO=$(gitrev-parse--short$ONTO)-iftest-z"$REBASE_ROOT"-# this is now equivalent to ! -z "$UPSTREAM"-then-SHORTUPSTREAM=$(gitrev-parse--short$UPSTREAM)-REVISIONS=$UPSTREAM...$HEAD-SHORTREVISIONS=$SHORTUPSTREAM..$SHORTHEAD-else-REVISIONS=$ONTO...$HEAD-SHORTREVISIONS=$SHORTHEAD-fi-gitrev-list$MERGES_OPTION--pretty=oneline--abbrev-commit\---abbrev=7--reverse--left-right--topo-order\-$REVISIONS|\-sed-n"s/^>//p"|-whileread-rshortsha1rest+iftest-z"$REBASE_ROOT"+then+UPSTREAM_ARG="$1"+UPSTREAM=$(gitrev-parse--verify"$1")||die"Invalid base"+test-z"$ONTO"&&ONTO=$UPSTREAM+shift+else+UPSTREAM=+UPSTREAM_ARG=--root+test-z"$ONTO"&&+die"You must specify --onto when using --root"+fi+run_pre_rebase_hook"$UPSTREAM_ARG""$@"++comment_for_reflogstart++require_clean_work_tree"rebase""Please commit or stash them."++iftest!-z"$1"+then+outputgitcheckout"$1"--||+die"Could not checkout $1"+fi++HEAD=$(gitrev-parse--verifyHEAD)||die"No HEAD?"+mkdir"$DOTEST"||die"Could not create temporary $DOTEST"++:>"$DOTEST"/interactive||die"Could not mark as interactive"+gitsymbolic-refHEAD>"$DOTEST"/head-name2>/dev/null||+echo"detached HEAD">"$DOTEST"/head-name++echo$HEAD>"$DOTEST"/head+case"$REBASE_ROOT"in+'')+rm-f"$DOTEST"/rebase-root;;+*)+:>"$DOTEST"/rebase-root;;+esac+echo$ONTO>"$DOTEST"/onto+test-z"$STRATEGY"||echo"$STRATEGY">"$DOTEST"/strategy+testt="$VERBOSE"&&:>"$DOTEST"/verbose+iftestt="$PRESERVE_MERGES"+then+iftest-z"$REBASE_ROOT"+then+mkdir"$REWRITTEN"&&+forcin$(gitmerge-base--all$HEAD$UPSTREAM)do-iftestt!="$PRESERVE_MERGES"-then-printf'%s\n'"pick $shortsha1$rest">>"$TODO"-else-sha1=$(gitrev-parse$shortsha1)-iftest-z"$REBASE_ROOT"-then-preserve=t-forpin$(gitrev-list--parents-1$sha1|cut-d' '-s-f2-)-do-iftest-f"$REWRITTEN"/$p-a\($p!=$ONTO-o$sha1=$first_after_upstream\)-then-preserve=f-fi-done-else-preserve=f-fi-iftestf="$preserve"-then-touch"$REWRITTEN"/$sha1-printf'%s\n'"pick $shortsha1$rest">>"$TODO"-fi-fi+echo$ONTO>"$REWRITTEN"/$c||+die"Could not init rewritten commits"done--# Watch for commits that been dropped by --cherry-pick-iftestt="$PRESERVE_MERGES"+else+mkdir"$REWRITTEN"&&+echo$ONTO>"$REWRITTEN"/root||+die"Could not init rewritten commits"+fi+# No cherry-pick because our first pass is to determine+# parents to rewrite and skipping dropped commits would+# prematurely end our probe+MERGES_OPTION=+first_after_upstream="$(gitrev-list--reverse--first-parent$UPSTREAM..$HEAD|head-n1)"+else+MERGES_OPTION="--no-merges --cherry-pick"+fi++SHORTHEAD=$(gitrev-parse--short$HEAD)+SHORTONTO=$(gitrev-parse--short$ONTO)+iftest-z"$REBASE_ROOT"+# this is now equivalent to ! -z "$UPSTREAM"+then+SHORTUPSTREAM=$(gitrev-parse--short$UPSTREAM)+REVISIONS=$UPSTREAM...$HEAD+SHORTREVISIONS=$SHORTUPSTREAM..$SHORTHEAD+else+REVISIONS=$ONTO...$HEAD+SHORTREVISIONS=$SHORTHEAD+fi+gitrev-list$MERGES_OPTION--pretty=oneline--abbrev-commit\+--abbrev=7--reverse--left-right--topo-order\+$REVISIONS|\+sed-n"s/^>//p"|+whileread-rshortsha1rest+do+iftestt!="$PRESERVE_MERGES"+then+printf'%s\n'"pick $shortsha1$rest">>"$TODO"+else+sha1=$(gitrev-parse$shortsha1)+iftest-z"$REBASE_ROOT"then-mkdir"$DROPPED"-# Save all non-cherry-picked changes-gitrev-list$REVISIONS--left-right--cherry-pick|\-sed-n"s/^>//p">"$DOTEST"/not-cherry-picks-# Now all commits and note which ones are missing in-# not-cherry-picks and hence being dropped-gitrev-list$REVISIONS|-whilereadrev+preserve=t+forpin$(gitrev-list--parents-1$sha1|cut-d' '-s-f2-)do-iftest-f"$REWRITTEN"/$rev-a"$(sane_grep"$rev""$DOTEST"/not-cherry-picks)"=""+iftest-f"$REWRITTEN"/$p-a\($p!=$ONTO-o$sha1=$first_after_upstream\)then-# Use -f2 because if rev-list is telling us this commit is-# not worthwhile, we don't want to track its multiple heads,-# just the history of its first-parent for others that will-# be rebasing on top of it-gitrev-list--parents-1$rev|cut-d' '-s-f2>"$DROPPED"/$rev-short=$(gitrev-list-1--abbrev-commit--abbrev=7$rev)-sane_grep-v"^[a-z][a-z]* $short"<"$TODO">"${TODO}2";mv"${TODO}2""$TODO"-rm"$REWRITTEN"/$rev+preserve=ffidone+else+preserve=f+fi+iftestf="$preserve"+then+touch"$REWRITTEN"/$sha1+printf'%s\n'"pick $shortsha1$rest">>"$TODO"fi+fi+done-test-s"$TODO"||echonoop>>"$TODO"-test-n"$AUTOSQUASH"&&rearrange_squash"$TODO"-cat>>"$TODO"<<EOF+# Watch for commits that been dropped by --cherry-pick+iftestt="$PRESERVE_MERGES"+then+mkdir"$DROPPED"+# Save all non-cherry-picked changes+gitrev-list$REVISIONS--left-right--cherry-pick|\+sed-n"s/^>//p">"$DOTEST"/not-cherry-picks+# Now all commits and note which ones are missing in+# not-cherry-picks and hence being dropped+gitrev-list$REVISIONS|+whilereadrev+do+iftest-f"$REWRITTEN"/$rev-a"$(sane_grep"$rev""$DOTEST"/not-cherry-picks)"=""+then+# Use -f2 because if rev-list is telling us this commit is+# not worthwhile, we don't want to track its multiple heads,+# just the history of its first-parent for others that will+# be rebasing on top of it+gitrev-list--parents-1$rev|cut-d' '-s-f2>"$DROPPED"/$rev+short=$(gitrev-list-1--abbrev-commit--abbrev=7$rev)+sane_grep-v"^[a-z][a-z]* $short"<"$TODO">"${TODO}2";mv"${TODO}2""$TODO"+rm"$REWRITTEN"/$rev+fi+done+fi++test-s"$TODO"||echonoop>>"$TODO"+test-n"$AUTOSQUASH"&&rearrange_squash"$TODO"+cat>>"$TODO"<<EOF# Rebase $SHORTREVISIONS onto $SHORTONTO#
@@ -1028,22 +1034,18 @@ first and then run 'git rebase --continue' again."# EOF-has_action"$TODO"||-die_abort"Nothing to do"+has_action"$TODO"||+die_abort"Nothing to do"-cp"$TODO""$TODO".backup-git_editor"$TODO"||-die_abort"Could not execute editor"+cp"$TODO""$TODO".backup+git_editor"$TODO"||+die_abort"Could not execute editor"-has_action"$TODO"||-die_abort"Nothing to do"+has_action"$TODO"||+die_abort"Nothing to do"-test-d"$REWRITTEN"||test-n"$NEVER_FF"||skip_unnecessary_picks+test-d"$REWRITTEN"||test-n"$NEVER_FF"||skip_unnecessary_picks-outputgitcheckout$ONTO||die_abort"could not detach HEAD"-gitupdate-refORIG_HEAD$HEAD-do_rest-;;-esac-shift-done+outputgitcheckout$ONTO||die_abort"could not detach HEAD"+gitupdate-refORIG_HEAD$HEAD+do_rest
@@ -62,6 +62,8 @@ in_progress=type=# One of {"$GIT_DIR"/rebase-apply, "$GIT_DIR"/rebase-merge}state_dir=+# One of {'', continue, skip, abort}, as parsed from command line+action= read_state(){iftest"$type"=merge
@@ -236,66 +238,10 @@ do--verify)OK_TO_SKIP_PRE_REBASE=;;---continue)-test-z"$in_progress"&&die"No rebase in progress?"--gitupdate-index--ignore-submodules--refresh&&-gitdiff-files--quiet--ignore-submodules||{-echo"You must edit all merge conflicts and then"-echo"mark them as resolved using git add"-exit1-}-read_state-iftest-d"$merge_dir"-then-continue_merge-whiletest"$msgnum"-le"$end"-do-call_merge"$msgnum"-continue_merge-done-finish_rb_merge-exit-fi-gitam--resolved--3way--resolvemsg="$RESOLVEMSG"&&-move_to_original_branch-exit-;;---skip)-test-z"$in_progress"&&die"No rebase in progress?"--gitreset--hardHEAD||exit$?-read_state-iftest-d"$merge_dir"-then-gitrerereclear-msgnum=$(($msgnum+1))-whiletest"$msgnum"-le"$end"-do-call_merge"$msgnum"-continue_merge-done-finish_rb_merge-exit-fi-gitam-3--skip--resolvemsg="$RESOLVEMSG"&&-move_to_original_branch-exit-;;---abort)-test-z"$in_progress"&&die"No rebase in progress?"--gitrerereclear-read_state-case"$head_name"in-refs/*)-gitsymbolic-refHEAD$head_name||-die"Could not move back to $head_name"-;;-esac-gitreset--hard$orig_head-rm-r"$state_dir"-exit+--continue|--skip|--abort)+action=${1##--}+shift+break;;--onto)test2-le"$#"||usage
@@ -391,6 +337,66 @@ dodonetest$#-gt2&&usage+test-n"$action"&&test-z"$in_progress"&&die"No rebase in progress?"++case"$action"in+continue)+gitupdate-index--ignore-submodules--refresh&&+gitdiff-files--quiet--ignore-submodules||{+echo"You must edit all merge conflicts and then"+echo"mark them as resolved using git add"+exit1+}+read_state+iftest-d"$merge_dir"+then+continue_merge+whiletest"$msgnum"-le"$end"+do+call_merge"$msgnum"+continue_merge+done+finish_rb_merge+exit+fi+gitam--resolved--3way--resolvemsg="$RESOLVEMSG"&&+move_to_original_branch+exit+;;+skip)+gitreset--hardHEAD||exit$?+read_state+iftest-d"$merge_dir"+then+gitrerereclear+msgnum=$(($msgnum+1))+whiletest"$msgnum"-le"$end"+do+call_merge"$msgnum"+continue_merge+done+finish_rb_merge+exit+fi+gitam-3--skip--resolvemsg="$RESOLVEMSG"&&+move_to_original_branch+exit+;;+abort)+gitrerereclear+read_state+case"$head_name"in+refs/*)+gitsymbolic-refHEAD$head_name||+die"Could not move back to $head_name"+;;+esac+gitreset--hard$orig_head+rm-r"$state_dir"+exit+;;+esac+# Make sure no rebase is in progressiftest-n"$in_progress"then
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:30
git-rebase--interactive.sh will soon be sourced from
git-rebase.sh. Align the names of variables used in these scripts to
prepare for that.
Some names in git-rebase--interactive.sh, such as "author_script" and
"amend", are currently used in their upper case form to refer to a
file and in their lower case form to refer to something else. In these
cases, change the name of the existing lower case variable and
downcase the name of the variable that refers to the file.
Currently, git-rebase.sh uses mostly lower case variable names, while
git-rebase--interactive.sh uses mostly upper case variable names. For
consistency, downcase all variables, not just the ones that will be
shared between the two script files.
Helped-by: Thomas Rast [off-list ref]
Signed-off-by: Martin von Zweigbergk <redacted>
---
Changes since v1:
* As suggested by Thomas, downcase *all* variables, so that the end
result looks consistent.
git-rebase--interactive.sh | 480 ++++++++++++++++++++++----------------------
git-rebase.sh | 32 ++--
2 files changed, 256 insertions(+), 256 deletions(-)
@@ -36,22 +36,22 @@ autosquash move commits that begin with squash!/fixup! under -i .git-sh-setup require_work_tree-DOTEST="$GIT_DIR/rebase-merge"+dotest="$GIT_DIR/rebase-merge"# The file containing rebase commands, comments, and empty lines.# This file is created by "git rebase -i" then edited by the user. As# the lines are processed, they are removed from the front of this-# file and written to the tail of $DONE.-TODO="$DOTEST"/git-rebase-todo+# file and written to the tail of $done.+todo="$dotest"/git-rebase-todo# The rebase command lines that have already been processed. A line# is moved here when it is first handled, before any associated user# actions.-DONE="$DOTEST"/done+done="$dotest"/done# The commit message that is planned to be used for any changes that# need to be committed following a user interaction.-MSG="$DOTEST"/message+msg="$dotest"/message# The file into which is accumulated the suggested commit message for# squash/fixup commands. When the first of a series of squash/fixups
@@ -61,34 +61,34 @@ MSG="$DOTEST"/message# is appended to the file as it is processed.## The first line of the file is of the form-# # This is a combination of $COUNT commits.-# where $COUNT is the number of commits whose messages have been+# # This is a combination of $count commits.+# where $count is the number of commits whose messages have been# written to the file so far (including the initial "pick" commit).# Each time that a commit message is processed, this line is read and# updated. It is deleted just before the combined commit is made.-SQUASH_MSG="$DOTEST"/message-squash+squash_msg="$dotest"/message-squash# If the current series of squash/fixups has not yet included a squash# command, then this file exists and holds the commit message of the# original "pick" commit. (If the series ends without a "squash"# command, then this can be used as the commit message of the combined# commit without opening the editor.)-FIXUP_MSG="$DOTEST"/message-fixup+fixup_msg="$dotest"/message-fixup-# $REWRITTEN is the name of a directory containing files for each-# commit that is reachable by at least one merge base of $HEAD and-# $UPSTREAM. They are not necessarily rewritten, but their children+# $rewritten is the name of a directory containing files for each+# commit that is reachable by at least one merge base of $head and+# $upstream. They are not necessarily rewritten, but their children# might be. This ensures that commits on merged, but otherwise# unrelated side branches are left alone. (Think "X" in the man page's# example.)-REWRITTEN="$DOTEST"/rewritten+rewritten="$dotest"/rewritten-DROPPED="$DOTEST"/dropped+dropped="$dotest"/dropped# A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and# GIT_AUTHOR_DATE that will be used for the commit that is currently# being rebased.-AUTHOR_SCRIPT="$DOTEST"/author-script+author_script="$dotest"/author-script# When an "edit" rebase command is being processed, the SHA1 of the# commit to be edited is recorded in this file. When "git rebase
@@ -96,24 +96,24 @@ AUTHOR_SCRIPT="$DOTEST"/author-script# will be amended to the HEAD commit, but only provided the HEAD# commit is still the commit to be edited. When any other rebase# command is processed, this file is deleted.-AMEND="$DOTEST"/amend+amend="$dotest"/amend# For the post-rewrite hook, we make a list of rewritten commits and# their new sha1s. The rewritten-pending list keeps the sha1s of# commits that have been processed, but not committed yet,# e.g. because they are waiting for a 'squash' command.-REWRITTEN_LIST="$DOTEST"/rewritten-list-REWRITTEN_PENDING="$DOTEST"/rewritten-pending--PRESERVE_MERGES=-STRATEGY=-ONTO=-VERBOSE=-OK_TO_SKIP_PRE_REBASE=-REBASE_ROOT=-AUTOSQUASH=-test"$(gitconfig--boolrebase.autosquash)"="true"&&AUTOSQUASH=t-NEVER_FF=+rewritten_list="$dotest"/rewritten-list+rewritten_pending="$dotest"/rewritten-pending++preserve_merges=+strategy=+onto=+verbose=+ok_to_skip_pre_rebase=+rebase_root=+autosquash=+test"$(gitconfig--boolrebase.autosquash)"="true"&&autosquash=t+force_rebase=GIT_CHERRY_PICK_HELP="\ hint:afterresolvingtheconflicts,markthecorrectedpaths
@@ -253,20 +253,20 @@ pick_one_preserving_merges () {esacsha1=$(gitrev-parse$sha1)-iftest-f"$DOTEST"/current-commit+iftest-f"$dotest"/current-committheniftest"$fast_forward"=tthenwhilereadcurrent_commitdo-gitrev-parseHEAD>"$REWRITTEN"/$current_commit-done<"$DOTEST"/current-commit-rm"$DOTEST"/current-commit||+gitrev-parseHEAD>"$rewritten"/$current_commit+done<"$dotest"/current-commit+rm"$dotest"/current-commit||die"Cannot write current commit's replacement sha1"fifi-echo$sha1>>"$DOTEST"/current-commit+echo$sha1>>"$dotest"/current-commit# rewrite parents; if none were rewritten, we can fast-forward.new_parents=
@@ -280,9 +280,9 @@ pick_one_preserving_merges () {p=$(expr"$pend":' \([^ ]*\)')pend="${pend# $p}"-iftest-f"$REWRITTEN"/$p+iftest-f"$rewritten"/$pthen-new_p=$(cat"$REWRITTEN"/$p)+new_p=$(cat"$rewritten"/$p)# If the todo reordered commits, and our parent is marked for# rewriting, but hasn't been gotten to yet, assume the user meant to
@@ -333,18 +333,18 @@ pick_one_preserving_merges () {test"a$1"=a-n&&die"Refusing to squash a merge: $sha1"# redo merge-author_script=$(get_author_ident_from_commit$sha1)-eval"$author_script"-msg="$(commit_message$sha1)"+author_script_content=$(get_author_ident_from_commit$sha1)+eval"$author_script_content"+msg_content="$(commit_message$sha1)"# No point in merging the first parent, that's HEADnew_parents=${new_parents# $first_parent}if!do_with_authoroutput\-gitmerge$STRATEGY-m"$msg"$new_parents+gitmerge$strategy-m"$msg_content"$new_parentsthen-printf"%s\n""$msg">"$GIT_DIR"/MERGE_MSG+printf"%s\n""$msg_content">"$GIT_DIR"/MERGE_MSGdie_with_patch$sha1"Error redoing merge $sha1"fi-echo"$sha1$(gitrev-parseHEAD^0)">>"$REWRITTEN_LIST"+echo"$sha1$(gitrev-parseHEAD^0)">>"$rewritten_list";;*)outputgitcherry-pick"$@"||
@@ -365,46 +365,46 @@ nth_string () {} update_squash_messages(){-iftest-f"$SQUASH_MSG";then-mv"$SQUASH_MSG""$SQUASH_MSG".bak||exit-COUNT=$(($(sed-n\+iftest-f"$squash_msg";then+mv"$squash_msg""$squash_msg".bak||exit+count=$(($(sed-n\-e"1s/^# This is a combination of \(.*\) commits\./\1/p"\--e"q"<"$SQUASH_MSG".bak)+1))+-e"q"<"$squash_msg".bak)+1)){-echo"# This is a combination of $COUNT commits."+echo"# This is a combination of $count commits."sed-e1d-e'2,/^./{/^$/d-}'<"$SQUASH_MSG".bak-}>"$SQUASH_MSG"+}'<"$squash_msg".bak+}>"$squash_msg"else-commit_messageHEAD>"$FIXUP_MSG"||die"Cannot write $FIXUP_MSG"-COUNT=2+commit_messageHEAD>"$fixup_msg"||die"Cannot write $fixup_msg"+count=2{echo"# This is a combination of 2 commits."echo"# The first commit's message is:"echo-cat"$FIXUP_MSG"-}>"$SQUASH_MSG"+cat"$fixup_msg"+}>"$squash_msg"ficase$1insquash)-rm-f"$FIXUP_MSG"+rm-f"$fixup_msg"echo-echo"# This is the $(nth_string$COUNT) commit message:"+echo"# This is the $(nth_string$count) commit message:"echocommit_message$2;;fixup)echo-echo"# The $(nth_string$COUNT) commit message will be skipped:"+echo"# The $(nth_string$count) commit message will be skipped:"echocommit_message$2|sed-e's/^/# /';;-esac>>"$SQUASH_MSG"+esac>>"$squash_msg"} peek_next_command(){-sed-n-e"/^#/d"-e'/^$/d'-e"s/ .*//p"-e"q"<"$TODO"+sed-n-e"/^#/d"-e'/^$/d'-e"s/ .*//p"-e"q"<"$todo"}# A squash/fixup has failed. Prepare the long version of the squash
@@ -414,24 +414,24 @@ peek_next_command () {# messages, effectively causing the combined commit to be used as the# new basis for any further squash/fixups. Args: sha1 rest die_failed_squash(){-mv"$SQUASH_MSG""$MSG"||exit-rm-f"$FIXUP_MSG"-cp"$MSG""$GIT_DIR"/MERGE_MSG||exit+mv"$squash_msg""$msg"||exit+rm-f"$fixup_msg"+cp"$msg""$GIT_DIR"/MERGE_MSG||exitwarnwarn"Could not apply $1... $2"die_with_patch$1""} flush_rewritten_pending(){-test-s"$REWRITTEN_PENDING"||return+test-s"$rewritten_pending"||returnnewsha1="$(gitrev-parseHEAD^0)"-sed"s/$/ $newsha1/"<"$REWRITTEN_PENDING">>"$REWRITTEN_LIST"-rm-f"$REWRITTEN_PENDING"+sed"s/$/ $newsha1/"<"$rewritten_pending">>"$rewritten_list"+rm-f"$rewritten_pending"} record_in_rewritten(){oldsha1="$(gitrev-parse$1)"-echo"$oldsha1">>"$REWRITTEN_PENDING"+echo"$oldsha1">>"$rewritten_pending"case"$(peek_next_command)"insquash|s|fixup|f)
@@ -472,9 +472,9 @@ do_next () {mark_action_donepick_one$sha1||die_with_patch$sha1"Could not apply $sha1... $rest"-echo"$sha1">"$DOTEST"/stopped-sha+echo"$sha1">"$dotest"/stopped-shamake_patch$sha1-gitrev-parse--verifyHEAD>"$AMEND"+gitrev-parse--verifyHEAD>"$amend"warn"Stopped at $sha1... $rest"warn"You can amend the commit now, with"warn
@@ -497,47 +497,47 @@ do_next () {esaccomment_for_reflog$squash_style-test-f"$DONE"&&has_action"$DONE"||+test-f"$done"&&has_action"$done"||die"Cannot '$squash_style' without a previous commit"mark_action_doneupdate_squash_messages$squash_style$sha1-author_script=$(get_author_ident_from_commitHEAD)-echo"$author_script">"$AUTHOR_SCRIPT"-eval"$author_script"+author_script_content=$(get_author_ident_from_commitHEAD)+echo"$author_script_content">"$author_script"+eval"$author_script_content"outputgitreset--softHEAD^pick_one-n$sha1||die_failed_squash$sha1"$rest"case"$(peek_next_command)"insquash|s|fixup|f)# This is an intermediate commit; its message will only be# used in case of trouble. So use the long version:-do_with_authoroutputgitcommit--no-verify-F"$SQUASH_MSG"||+do_with_authoroutputgitcommit--no-verify-F"$squash_msg"||die_failed_squash$sha1"$rest";;*)# This is the final command of this squash/fixup group-iftest-f"$FIXUP_MSG"+iftest-f"$fixup_msg"then-do_with_authorgitcommit--no-verify-F"$FIXUP_MSG"||+do_with_authorgitcommit--no-verify-F"$fixup_msg"||die_failed_squash$sha1"$rest"else-cp"$SQUASH_MSG""$GIT_DIR"/SQUASH_MSG||exit+cp"$squash_msg""$GIT_DIR"/SQUASH_MSG||exitrm-f"$GIT_DIR"/MERGE_MSGdo_with_authorgitcommit--no-verify-e||die_failed_squash$sha1"$rest"fi-rm-f"$SQUASH_MSG""$FIXUP_MSG"+rm-f"$squash_msg""$fixup_msg";;esacrecord_in_rewritten$sha1;;x|"exec")-read-rcommandrest<"$TODO"+read-rcommandrest<"$todo"mark_action_doneprintf'Executing: %s\n'"$rest"# "exec" command doesn't take a sha1 in the todo-list.# => can't just use $sha1 here.-gitrev-parse--verifyHEAD>"$DOTEST"/stopped-sha+gitrev-parse--verifyHEAD>"$dotest"/stopped-sha${SHELL:-@SHELL_PATH@}-c"$rest"# Actual executionstatus=$?iftest"$status"-ne0
@@ -563,42 +563,42 @@ do_next () {warn"Unknown command: $command$sha1$rest"ifgitrev-parse--verify-q"$sha1">/dev/nullthen-die_with_patch$sha1"Please fix this in the file $TODO."+die_with_patch$sha1"Please fix this in the file $todo."else-die"Please fix this in the file $TODO."+die"Please fix this in the file $todo."fi;;esac-test-s"$TODO"&&return+test-s"$todo"&&returncomment_for_reflogfinish&&-HEADNAME=$(cat"$DOTEST"/head-name)&&-OLDHEAD=$(cat"$DOTEST"/head)&&-SHORTONTO=$(gitrev-parse--short$(cat"$DOTEST"/onto))&&-NEWHEAD=$(gitrev-parseHEAD)&&-case$HEADNAMEin+headname=$(cat"$dotest"/head-name)&&+oldhead=$(cat"$dotest"/head)&&+shortonto=$(gitrev-parse--short$(cat"$dotest"/onto))&&+newhead=$(gitrev-parseHEAD)&&+case$headnameinrefs/*)-message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO"&&-gitupdate-ref-m"$message"$HEADNAME$NEWHEAD$OLDHEAD&&-gitsymbolic-refHEAD$HEADNAME+message="$GIT_REFLOG_ACTION: $headname onto $shortonto"&&+gitupdate-ref-m"$message"$headname$newhead$oldhead&&+gitsymbolic-refHEAD$headname;;esac&&{-test!-f"$DOTEST"/verbose||-gitdiff-tree--stat$(cat"$DOTEST"/head)..HEAD+test!-f"$dotest"/verbose||+gitdiff-tree--stat$(cat"$dotest"/head)..HEAD}&&{-test-s"$REWRITTEN_LIST"&&-gitnotescopy--for-rewrite=rebase<"$REWRITTEN_LIST"||+test-s"$rewritten_list"&&+gitnotescopy--for-rewrite=rebase<"$rewritten_list"||true# we don't care if this copying failed}&&iftest-x"$GIT_DIR"/hooks/post-rewrite&&-test-s"$REWRITTEN_LIST";then-"$GIT_DIR"/hooks/post-rewriterebase<"$REWRITTEN_LIST"+test-s"$rewritten_list";then+"$GIT_DIR"/hooks/post-rewriterebase<"$rewritten_list"true# we don't care if this hook failedfi&&-rm-rf"$DOTEST"&&+rm-rf"$dotest"&&gitgc--auto&&-warn"Successfully rebased and updated $HEADNAME."+warn"Successfully rebased and updated $headname."exit}
@@ -618,11 +618,11 @@ skip_unnecessary_picks () {# fd=3 means we skip the commandcase"$fd,$command"in3,pick|3,p)-# pick a commit whose parent is current $ONTO -> skip+# pick a commit whose parent is current $onto -> skipsha1=${rest%% *}case"$(gitrev-parse--verify--quiet"$sha1"^)"in-"$ONTO"*)-ONTO=$sha1+"$onto"*)+onto=$sha1;;*)fd=1
@@ -650,17 +650,17 @@ skip_unnecessary_picks () {# check if no other options are set is_standalone(){test$#-eq2-a"$2"='--'&&-test-z"$ONTO"&&-test-z"$PRESERVE_MERGES"&&-test-z"$STRATEGY"&&-test-z"$VERBOSE"+test-z"$onto"&&+test-z"$preserve_merges"&&+test-z"$strategy"&&+test-z"$verbose"} get_saved_options(){-test-d"$REWRITTEN"&&PRESERVE_MERGES=t-test-f"$DOTEST"/strategy&&STRATEGY="$(cat"$DOTEST"/strategy)"-test-f"$DOTEST"/verbose&&VERBOSE=t-test-f"$DOTEST"/rebase-root&&REBASE_ROOT=t+test-d"$rewritten"&&preserve_merges=t+test-f"$dotest"/strategy&&strategy="$(cat"$dotest"/strategy)"+test-f"$dotest"/verbose&&verbose=t+test-f"$dotest"/rebase-root&&rebase_root=t}# Rearrange the todo list that has both "pick sha1 msg" and
@@ -747,17 +747,17 @@ while test $# != 0docase"$1"in--no-verify)-OK_TO_SKIP_PRE_REBASE=yes+ok_to_skip_pre_rebase=yes;;--verify)-OK_TO_SKIP_PRE_REBASE=+ok_to_skip_pre_rebase=;;--continue)is_standalone"$@"||usageget_saved_optionscomment_for_reflogcontinue-test-d"$DOTEST"||die"No interactive rebase running"+test-d"$dotest"||die"No interactive rebase running"# Sanity checkgitrev-parse--verifyHEAD>/dev/null||
@@ -771,26 +771,26 @@ dothen:Nothingtocommit--skipthiselse-."$AUTHOR_SCRIPT"||+."$author_script"||die"Cannot find the author identity"-amend=-iftest-f"$AMEND"+current_head=+iftest-f"$amend"then-amend=$(gitrev-parse--verifyHEAD)-test"$amend"=$(cat"$AMEND")||+current_head=$(gitrev-parse--verifyHEAD)+test"$current_head"=$(cat"$amend")||die"\ Youhaveuncommittedchangesinyourworkingtree.Please,committhem firstandthenrun'git rebase --continue'again."gitreset--softHEAD^||die"Cannot rewind the HEAD"fi-do_with_authorgitcommit--no-verify-F"$MSG"-e||{-test-n"$amend"&&gitreset--soft$amend+do_with_authorgitcommit--no-verify-F"$msg"-e||{+test-n"$current_head"&&gitreset--soft$current_headdie"Could not commit staged changes."}fi-record_in_rewritten"$(cat"$DOTEST"/stopped-sha)"+record_in_rewritten"$(cat"$dotest"/stopped-sha)"require_clean_work_tree"rebase"do_rest
@@ -801,17 +801,17 @@ first and then run 'git rebase --continue' again."comment_for_reflogabortgitrerereclear-test-d"$DOTEST"||die"No interactive rebase running"+test-d"$dotest"||die"No interactive rebase running"-HEADNAME=$(cat"$DOTEST"/head-name)-HEAD=$(cat"$DOTEST"/head)-case$HEADNAMEin+headname=$(cat"$dotest"/head-name)+head=$(cat"$dotest"/head)+case$headnameinrefs/*)-gitsymbolic-refHEAD$HEADNAME+gitsymbolic-refHEAD$headname;;esac&&-outputgitreset--hard$HEAD&&-rm-rf"$DOTEST"+outputgitreset--hard$head&&+rm-rf"$dotest"exit;;--skip)
@@ -820,18 +820,18 @@ first and then run 'git rebase --continue' again."comment_for_reflogskipgitrerereclear-test-d"$DOTEST"||die"No interactive rebase running"+test-d"$dotest"||die"No interactive rebase running"outputgitreset--hard&&do_rest;;-s)case"$#,$1"in*,*=*)-STRATEGY="-s "$(expr"z$1":'z-[^=]*=\(.*\)');;+strategy="-s "$(expr"z$1":'z-[^=]*=\(.*\)');;1,*)usage;;*)-STRATEGY="-s $2"+strategy="-s $2"shift;;esac;;
@@ -839,29 +839,29 @@ first and then run 'git rebase --continue' again."# we use merge anyway;;-v)-VERBOSE=t+verbose=t;;-p)-PRESERVE_MERGES=t+preserve_merges=t;;-i)# yeah, we know;;--no-ff)-NEVER_FF=t+force_rebase=t;;--root)-REBASE_ROOT=t+rebase_root=t;;--autosquash)-AUTOSQUASH=t+autosquash=t;;--no-autosquash)-AUTOSQUASH=+autosquash=;;--onto)shift-ONTO=$(parse_onto"$1")||+onto=$(parse_onto"$1")||die"Does not point to a valid commit: $1";;--)
@@ -872,27 +872,27 @@ first and then run 'git rebase --continue' again."shiftdone-test-z"$REBASE_ROOT"-a$#-ge1-a$#-le2||-test!-z"$REBASE_ROOT"-a$#-le1||usage-test-d"$DOTEST"&&+test-z"$rebase_root"-a$#-ge1-a$#-le2||+test!-z"$rebase_root"-a$#-le1||usage+test-d"$dotest"&&die"Interactive rebase already started" gitvarGIT_COMMITTER_IDENT>/dev/null||die"You need to set your committer info first"-iftest-z"$REBASE_ROOT"+iftest-z"$rebase_root"then-UPSTREAM_ARG="$1"-UPSTREAM=$(gitrev-parse--verify"$1")||die"Invalid base"-test-z"$ONTO"&&ONTO=$UPSTREAM+upstream_arg="$1"+upstream=$(gitrev-parse--verify"$1")||die"Invalid base"+test-z"$onto"&&onto=$upstreamshiftelse-UPSTREAM=-UPSTREAM_ARG=--root-test-z"$ONTO"&&-die"You must specify --onto when using --root"+upstream=+upstream_arg=--root+test-z"$onto"&&+die"You must specify --onto when using --root"fi-run_pre_rebase_hook"$UPSTREAM_ARG""$@"+run_pre_rebase_hook"$upstream_arg""$@" comment_for_reflogstart
@@ -904,76 +904,76 @@ thendie"Could not checkout $1"fi-HEAD=$(gitrev-parse--verifyHEAD)||die"No HEAD?"-mkdir"$DOTEST"||die"Could not create temporary $DOTEST"+head=$(gitrev-parse--verifyHEAD)||die"No HEAD?"+mkdir"$dotest"||die"Could not create temporary $dotest"-:>"$DOTEST"/interactive||die"Could not mark as interactive"-gitsymbolic-refHEAD>"$DOTEST"/head-name2>/dev/null||-echo"detached HEAD">"$DOTEST"/head-name+:>"$dotest"/interactive||die"Could not mark as interactive"+gitsymbolic-refHEAD>"$dotest"/head-name2>/dev/null||+echo"detached HEAD">"$dotest"/head-name-echo$HEAD>"$DOTEST"/head-case"$REBASE_ROOT"in+echo$head>"$dotest"/head+case"$rebase_root"in'')-rm-f"$DOTEST"/rebase-root;;+rm-f"$dotest"/rebase-root;; *)-:>"$DOTEST"/rebase-root;;+:>"$dotest"/rebase-root;;esac-echo$ONTO>"$DOTEST"/onto-test-z"$STRATEGY"||echo"$STRATEGY">"$DOTEST"/strategy-testt="$VERBOSE"&&:>"$DOTEST"/verbose-iftestt="$PRESERVE_MERGES"+echo$onto>"$dotest"/onto+test-z"$strategy"||echo"$strategy">"$dotest"/strategy+testt="$verbose"&&:>"$dotest"/verbose+iftestt="$preserve_merges"then-iftest-z"$REBASE_ROOT"+iftest-z"$rebase_root"then-mkdir"$REWRITTEN"&&-forcin$(gitmerge-base--all$HEAD$UPSTREAM)+mkdir"$rewritten"&&+forcin$(gitmerge-base--all$head$upstream)do-echo$ONTO>"$REWRITTEN"/$c||+echo$onto>"$rewritten"/$c||die"Could not init rewritten commits"doneelse-mkdir"$REWRITTEN"&&-echo$ONTO>"$REWRITTEN"/root||+mkdir"$rewritten"&&+echo$onto>"$rewritten"/root||die"Could not init rewritten commits"fi# No cherry-pick because our first pass is to determine# parents to rewrite and skipping dropped commits would# prematurely end our probe-MERGES_OPTION=-first_after_upstream="$(gitrev-list--reverse--first-parent$UPSTREAM..$HEAD|head-n1)"+merges_option=+first_after_upstream="$(gitrev-list--reverse--first-parent$upstream..$head|head-n1)"else-MERGES_OPTION="--no-merges --cherry-pick"+merges_option="--no-merges --cherry-pick"fi-SHORTHEAD=$(gitrev-parse--short$HEAD)-SHORTONTO=$(gitrev-parse--short$ONTO)-iftest-z"$REBASE_ROOT"-# this is now equivalent to ! -z "$UPSTREAM"+shorthead=$(gitrev-parse--short$head)+shortonto=$(gitrev-parse--short$onto)+iftest-z"$rebase_root"+# this is now equivalent to ! -z "$upstream"then-SHORTUPSTREAM=$(gitrev-parse--short$UPSTREAM)-REVISIONS=$UPSTREAM...$HEAD-SHORTREVISIONS=$SHORTUPSTREAM..$SHORTHEAD+shortupstream=$(gitrev-parse--short$upstream)+revisions=$upstream...$head+shortrevisions=$shortupstream..$shortheadelse-REVISIONS=$ONTO...$HEAD-SHORTREVISIONS=$SHORTHEAD+revisions=$onto...$head+shortrevisions=$shortheadfi-gitrev-list$MERGES_OPTION--pretty=oneline--abbrev-commit\+gitrev-list$merges_option--pretty=oneline--abbrev-commit\--abbrev=7--reverse--left-right--topo-order\-$REVISIONS|\+$revisions|\sed-n"s/^>//p"|whileread-rshortsha1restdo-iftestt!="$PRESERVE_MERGES"+iftestt!="$preserve_merges"then-printf'%s\n'"pick $shortsha1$rest">>"$TODO"+printf'%s\n'"pick $shortsha1$rest">>"$todo"elsesha1=$(gitrev-parse$shortsha1)-iftest-z"$REBASE_ROOT"+iftest-z"$rebase_root"thenpreserve=tforpin$(gitrev-list--parents-1$sha1|cut-d' '-s-f2-)do-iftest-f"$REWRITTEN"/$p-a\($p!=$ONTO-o$sha1=$first_after_upstream\)+iftest-f"$rewritten"/$p-a\($p!=$onto-o$sha1=$first_after_upstream\)thenpreserve=ffi
@@ -983,43 +983,43 @@ dofiiftestf="$preserve"then-touch"$REWRITTEN"/$sha1-printf'%s\n'"pick $shortsha1$rest">>"$TODO"+touch"$rewritten"/$sha1+printf'%s\n'"pick $shortsha1$rest">>"$todo"fifidone# Watch for commits that been dropped by --cherry-pick-iftestt="$PRESERVE_MERGES"+iftestt="$preserve_merges"then-mkdir"$DROPPED"+mkdir"$dropped"# Save all non-cherry-picked changes-gitrev-list$REVISIONS--left-right--cherry-pick|\-sed-n"s/^>//p">"$DOTEST"/not-cherry-picks+gitrev-list$revisions--left-right--cherry-pick|\+sed-n"s/^>//p">"$dotest"/not-cherry-picks# Now all commits and note which ones are missing in# not-cherry-picks and hence being dropped-gitrev-list$REVISIONS|+gitrev-list$revisions|whilereadrevdo-iftest-f"$REWRITTEN"/$rev-a"$(sane_grep"$rev""$DOTEST"/not-cherry-picks)"=""+iftest-f"$rewritten"/$rev-a"$(sane_grep"$rev""$dotest"/not-cherry-picks)"=""then# Use -f2 because if rev-list is telling us this commit is# not worthwhile, we don't want to track its multiple heads,# just the history of its first-parent for others that will# be rebasing on top of it-gitrev-list--parents-1$rev|cut-d' '-s-f2>"$DROPPED"/$rev+gitrev-list--parents-1$rev|cut-d' '-s-f2>"$dropped"/$revshort=$(gitrev-list-1--abbrev-commit--abbrev=7$rev)-sane_grep-v"^[a-z][a-z]* $short"<"$TODO">"${TODO}2";mv"${TODO}2""$TODO"-rm"$REWRITTEN"/$rev+sane_grep-v"^[a-z][a-z]* $short"<"$todo">"${todo}2";mv"${todo}2""$todo"+rm"$rewritten"/$revfidonefi-test-s"$TODO"||echonoop>>"$TODO"-test-n"$AUTOSQUASH"&&rearrange_squash"$TODO"-cat>>"$TODO"<<EOF+test-s"$todo"||echonoop>>"$todo"+test-n"$autosquash"&&rearrange_squash"$todo"+cat>>"$todo"<<EOF-# Rebase $SHORTREVISIONS onto $SHORTONTO+# Rebase $shortrevisions onto $shortonto## Commands:# p, pick = use commit
@@ -1034,18 +1034,18 @@ cat >> "$TODO" << EOF# EOF-has_action"$TODO"||+has_action"$todo"||die_abort"Nothing to do"-cp"$TODO""$TODO".backup-git_editor"$TODO"||+cp"$todo""$todo".backup+git_editor"$todo"||die_abort"Could not execute editor"-has_action"$TODO"||+has_action"$todo"||die_abort"Nothing to do"-test-d"$REWRITTEN"||test-n"$NEVER_FF"||skip_unnecessary_picks+test-d"$rewritten"||test-n"$force_rebase"||skip_unnecessary_picks-outputgitcheckout$ONTO||die_abort"could not detach HEAD"-gitupdate-refORIG_HEAD$HEAD+outputgitcheckout$onto||die_abort"could not detach HEAD"+gitupdate-refORIG_HEAD$head do_rest
@@ -86,7 +86,7 @@ continue_merge () {thenecho"You still have unmerged paths in your index"echo"did you forget to use git add?"-die"$RESOLVEMSG"+die"$resolvemsg"ficmt=`cat"$merge_dir/current"`
@@ -96,7 +96,7 @@ continue_merge () {thenecho"Commit failed, please do not call \"git commit\""echo"directly, but instead do one of the following: "-die"$RESOLVEMSG"+die"$resolvemsg"fiiftest-z"$GIT_QUIET"then
@@ -234,10 +234,10 @@ while test $# != 0docase"$1"in--no-verify)-OK_TO_SKIP_PRE_REBASE=yes+ok_to_skip_pre_rebase=yes;;--verify)-OK_TO_SKIP_PRE_REBASE=+ok_to_skip_pre_rebase=;;--continue|--skip|--abort)test$total_argc-eq1||usage
@@ -425,7 +425,7 @@ thenunsetroot_flagupstream_arg="$upstream_name"else-test-z"$newbase"&&die"--root must be used with --onto"+test-z"$onto"&&die"--root must be used with --onto"unsetupstream_nameunsetupstreamroot_flag="--root"
@@ -433,7 +433,7 @@ elsefi# Make sure the branch to rebase onto is valid.-onto_name=${newbase-"$upstream_name"}+onto_name=${onto-"$upstream_name"}case"$onto_name"in *...*)ifleft=${onto_name%...*}right=${onto_name#*...}&&
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:30
Make sure to interpret variables with the same name in the same way in
git-rebase.sh and git-rebase--interactive.sh. This will make it easier
to factor out code from git-rebase.sh to git-rebase--interactive and
export the variables.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 16 +++++++++++-----
git-rebase.sh | 4 +++-
2 files changed, 14 insertions(+), 6 deletions(-)
@@ -339,7 +339,8 @@ pick_one_preserving_merges () {# No point in merging the first parent, that's HEADnew_parents=${new_parents# $first_parent}if!do_with_authoroutput\-gitmerge$strategy-m"$msg_content"$new_parents+gitmerge${strategy:+-s $strategy}-m\+"$msg_content"$new_parentsthenprintf"%s\n""$msg_content">"$GIT_DIR"/MERGE_MSGdie_with_patch$sha1"Error redoing merge $sha1"
@@ -827,11 +828,11 @@ first and then run 'git rebase --continue' again."-s)case"$#,$1"in*,*=*)-strategy="-s "$(expr"z$1":'z-[^=]*=\(.*\)');;+strategy=$(expr"z$1":'z-[^=]*=\(.*\)');;1,*)usage;;*)-strategy="-s $2"+strategy="$2"shift;;esac;;
@@ -860,9 +861,9 @@ first and then run 'git rebase --continue' again."autosquash=;;--onto)+test2-le"$#"||usage+onto="$2"shift-onto=$(parse_onto"$1")||-die"Does not point to a valid commit: $1";;--)shift
@@ -872,6 +873,11 @@ first and then run 'git rebase --continue' again."shiftdone+iftest-n"$onto"+then+onto=$(parse_onto"$onto")||die"Does not point to a valid commit: $1"+fi+test-z"$rebase_root"-a$#-ge1-a$#-le2||test!-z"$rebase_root"-a$#-le1||usagetest-d"$dotest"&&
@@ -43,7 +43,7 @@ If you would prefer to skip this patch, instead run \"git rebase --skip\". Torestoretheoriginalbranchandstoprebasingrun\"gitrebase--abort\"."unsetonto-strategy=recursive+strategy=strategy_opts=do_merge=merge_dir="$GIT_DIR"/rebase-merge
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:31
Remove directory checks from git-rebase--interactive.sh that are done in
git-rebase.sh.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Squash with previous?
git-rebase--interactive.sh | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
@@ -749,7 +747,6 @@ abort)comment_for_reflogabortgitrerereclear-test-d"$dotest"||die"No interactive rebase running"headname=$(cat"$dotest"/head-name)head=$(cat"$dotest"/head)
@@ -767,7 +764,6 @@ skip)comment_for_reflogskipgitrerereclear-test-d"$dotest"||die"No interactive rebase running"outputgitreset--hard&&do_rest;;
@@ -780,8 +776,6 @@ fitest-z"$rebase_root"-a$#-ge1-a$#-le2||test!-z"$rebase_root"-a$#-le1||usage-test-d"$dotest"&&-die"Interactive rebase already started" gitvarGIT_COMMITTER_IDENT>/dev/null||die"You need to set your committer info first"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:31
The code reading the state saved in $merge_dir or $rebase_dir is
currently spread out in many places, making it harder to read and to
introduce additional state. Extract this code into one method that
reads the state. Only extract the code associated with the state that
is written when the rebase is initiated. Leave the state that changes
for each commmit, at least for now.
Currently, when resuming a merge-based rebase using --continue or
--skip, move_to_original_branch (via finish_rb_merge) will be called
without head_name and orig_head set. These variables are then lazily
read in move_to_original_branch if head_name is not set (together with
onto, which is unnecessarily read again). Change this by always
eagerly reading the state, for both am-based and merge-based rebase,
in the --continue and --skip cases. Note that this does not change the
behavior for am-based rebase, which read the state eagerly even before
this commit.
Reading the state eagerly means that part of the state will sometimes
be read unnecessarily. One example is when the rebase is continued,
but stops again at another merge conflict. Another example is when the
rebase is aborted. However, since both of these cases involve user
interaction, the delay is hopefully not noticeable. The
call_merge/continue_merge loop is not affected.
Helped-by: Junio C Hamano [off-list ref]
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase.sh | 53 +++++++++++++++++++++++------------------------------
1 files changed, 23 insertions(+), 30 deletions(-)
@@ -57,6 +57,22 @@ rebase_root=force_rebase=allow_rerere_autoupdate=+read_state(){+iftest-d"$merge_dir"+then+state_dir="$merge_dir"+prev_head=$(cat"$merge_dir"/prev_head)&&+end=$(cat"$merge_dir"/end)&&+msgnum=$(cat"$merge_dir"/msgnum)+else+state_dir="$apply_dir"+fi&&+head_name=$(cat"$state_dir"/head-name)&&+onto=$(cat"$state_dir"/onto)&&+orig_head=$(cat"$state_dir"/orig-head)&&+GIT_QUIET=$(cat"$state_dir"/quiet)+}+ continue_merge(){test-n"$prev_head"||die"prev_head must be defined"test-d"$merge_dir"||die"$merge_dir directory does not exist"
@@ -220,13 +232,9 @@ doecho"mark them as resolved using git add"exit1}+read_stateiftest-d"$merge_dir"then-prev_head=$(cat"$merge_dir/prev_head")-end=$(cat"$merge_dir/end")-msgnum=$(cat"$merge_dir/msgnum")-onto=$(cat"$merge_dir/onto")-GIT_QUIET=$(cat"$merge_dir/quiet")continue_mergewhiletest"$msgnum"-le"$end"do
@@ -249,15 +253,11 @@ dodie"No rebase in progress?"gitreset--hardHEAD||exit$?+read_stateiftest-d"$merge_dir"thengitrerereclear-prev_head=$(cat"$merge_dir/prev_head")-end=$(cat"$merge_dir/end")-msgnum=$(cat"$merge_dir/msgnum")msgnum=$(($msgnum+1))-onto=$(cat"$merge_dir/onto")-GIT_QUIET=$(cat"$merge_dir/quiet")whiletest"$msgnum"-le"$end"docall_merge"$msgnum"
@@ -279,18 +275,15 @@ dodie"No rebase in progress?"gitrerereclear--test-d"$merge_dir"||merge_dir="$apply_dir"--head_name="$(cat"$merge_dir"/head-name)"&&+read_statecase"$head_name"inrefs/*)gitsymbolic-refHEAD$head_name||die"Could not move back to $head_name";;esac-gitreset--hard$(cat"$merge_dir/orig-head")-rm-r"$merge_dir"+gitreset--hard$orig_head+rm-r"$state_dir"exit;;--onto)
@@ -574,12 +567,12 @@ fi# this is rename-aware if the recursive (default) strategy is used mkdir-p"$merge_dir"-echo"$onto">"$merge_dir/onto"echo"$onto_name">"$merge_dir/onto_name"prev_head=$orig_headecho"$prev_head">"$merge_dir/prev_head"-echo"$orig_head">"$merge_dir/orig-head"echo"$head_name">"$merge_dir/head-name"+echo"$onto">"$merge_dir/onto"+echo"$orig_head">"$merge_dir/orig-head"echo"$GIT_QUIET">"$merge_dir/quiet"msgnum=0
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:31
The sub commands '--continue', '--skip' or '--abort' may only be used
standalone according to the documentation. Other options following the
sub command are currently not accepted, but options preceeding them
are. For example, 'git rebase --continue -v' is not accepted, while
'git rebase -v --continue' is. Tighten up the check and allow no other
options when one of these sub commands are used.
Only check that it is standalone for non-interactive rebase for
now. Once the command line processing for interactive rebase has been
replaced by the command line processing in git-rebase.sh, this check
will also apply to interactive rebase.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Is this too simplistic? Do we forsee that we want to support passing
options when resuming a rebase? Is it better to check for each other
option that it is not passed (i.e. no '-v', no '-s' etc.)?
Might some users be depending on the current behavior, even though it
is undocumented?
git-rebase.sh | 4 ++--
t/t3403-rebase-skip.sh | 5 +++++
t/t3407-rebase-abort.sh | 10 ++++++++++
t/t3418-rebase-continue.sh | 5 +++++
4 files changed, 22 insertions(+), 2 deletions(-)
@@ -35,6 +35,11 @@ test_expect_success 'rebase with git am -3 (default)' 'test_must_failgitrebasemaster'+test_expect_success'rebase --skip can not be used with other options''+test_must_failgitrebase-v--skip&&+test_must_failgitrebase--skip-v+'+ test_expect_success'rebase --skip with am -3''gitrebase--skip'
@@ -84,6 +84,16 @@ testrebase() {test_cmpreflog_beforereflog_after&&rmreflog_beforereflog_after'++test_expect_success'rebase --abort can not be used with other options''+cd"$work_dir"&&+# Clean up the state from the previous one+gitreset--hardpre-rebase&&+test_must_failgitrebase$typemaster&&+test_must_failgitrebase-v--abort&&+test_must_failgitrebase--abort-v&&+gitrebase--abort+'} testrebase"".git/rebase-apply
@@ -40,4 +40,9 @@ test_expect_success 'non-interactive rebase --continue works with touched file'gitrebase--continue'+test_expect_success'rebase --continue can not be used with other options''+test_must_failgitrebase-v--continue&&+test_must_failgitrebase--continue-v+'+ test_done
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:31
Remove the parsing and validation of references (onto, upstream, branch)
from git-rebase--interactive.sh and rely on the information exported from
git-rebase.sh.
By using the parsing of the --onto parameter in git-rebase.sh, this
improves the error message when the parameter is invalid.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Should the check for set GIT_COMMITTER_IDENT be done for
non-interactive rebase as well or does it only make sense for
interactive rebase?
git-rebase--interactive.sh | 48 +++----------------------------------------
git-rebase.sh | 9 ++++---
2 files changed, 9 insertions(+), 48 deletions(-)
@@ -769,47 +750,26 @@ skip);;esac-iftest-n"$onto"-then-onto=$(parse_onto"$onto")||die"Does not point to a valid commit: $1"-fi--test-z"$rebase_root"-a$#-ge1-a$#-le2||-test!-z"$rebase_root"-a$#-le1||usage- gitvarGIT_COMMITTER_IDENT>/dev/null||die"You need to set your committer info first"-iftest-z"$rebase_root"-then-upstream_arg="$1"-upstream=$(gitrev-parse--verify"$1")||die"Invalid base"-test-z"$onto"&&onto=$upstream-shift-else-upstream=-upstream_arg=--root-test-z"$onto"&&-die"You must specify --onto when using --root"-fi require_clean_work_tree"rebase""Please commit or stash them." run_pre_rebase_hook"$upstream_arg""$@" comment_for_reflogstart-iftest!-z"$1"+iftest!-z"$switch_to"then-outputgitcheckout"$1"--||-die"Could not checkout $1"+outputgitcheckout"$switch_to"--||+die"Could not checkout $switch_to"fihead=$(gitrev-parse--verifyHEAD)||die"No HEAD?" mkdir"$dotest"||die"Could not create temporary $dotest" :>"$dotest"/interactive||die"Could not mark as interactive"-gitsymbolic-refHEAD>"$dotest"/head-name2>/dev/null||-echo"detached HEAD">"$dotest"/head-name+echo"$head_name">"$dotest"/head-nameecho$head>"$dotest"/headcase"$rebase_root"in
@@ -431,8 +431,6 @@ elsestate_dir="$apply_dir"fi-test"$type"=interactive&&run_interactive_rebase"$@"-iftest-z"$rebase_root"then# The upstream head must be given. Make sure it is valid.
@@ -443,7 +441,7 @@ thenunsetroot_flagupstream_arg="$upstream_name"else-test-z"$onto"&&die"--root must be used with --onto"+test-z"$onto"&&die"You must specify --onto when using --root"unsetupstream_nameunsetupstreamroot_flag="--root"
@@ -470,7 +468,8 @@ case "$onto_name" infi;; *)-onto=$(gitrev-parse--verify"${onto_name}^0")||exit+onto=$(gitrev-parse--verify"${onto_name}^0")||+die"Does not point to a valid commit: $1";;esac
@@ -512,6 +511,8 @@ case "$#" inesacorig_head=$branch+test"$type"=interactive&&run_interactive_rebase"$@"+ require_clean_work_tree"rebase""Please commit or stash them."# Now we are rebasing commits $upstream..$branch (or with --root,
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:31
Reorder validation steps in preparation for the validation to be factored
out from git-rebase--interactive.sh into git-rebase.sh.
The main functional difference is that the pre-rebase hook will no longer
be run if the work tree is dirty.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 4 ++--
git-rebase.sh | 10 +++++-----
2 files changed, 7 insertions(+), 7 deletions(-)
@@ -792,12 +792,12 @@ elsetest-z"$onto"&&die"You must specify --onto when using --root"fi+require_clean_work_tree"rebase""Please commit or stash them."+ run_pre_rebase_hook"$upstream_arg""$@" comment_for_reflogstart-require_clean_work_tree"rebase""Please commit or stash them."-iftest!-z"$1"thenoutputgitcheckout"$1"--||
@@ -433,8 +433,6 @@ fitest"$type"=interactive&&run_interactive_rebase"$@"-require_clean_work_tree"rebase""Please commit or stash them."-iftest-z"$rebase_root"then# The upstream head must be given. Make sure it is valid.
@@ -476,9 +474,6 @@ case "$onto_name" in;;esac-# If a hook exists, give it a chance to interrupt-run_pre_rebase_hook"$upstream_arg""$@"-# If the branch to rebase is given, that is the branch we will rebase# $branch_name -- branch being rebased, or HEAD (already detached)# $orig_head -- commit object name of tip of the branch before rebasing
@@ -517,6 +512,8 @@ case "$#" inesacorig_head=$branch+require_clean_work_tree"rebase""Please commit or stash them."+# Now we are rebasing commits $upstream..$branch (or with --root,# everything leading up to $branch) on top of $onto
@@ -538,6 +535,9 @@ thenfifi+# If a hook exists, give it a chance to interrupt+run_pre_rebase_hook"$upstream_arg""$@"+# Detach HEAD and reset the tree say"First, rewinding head to replay your work on top of it..." gitcheckout-q"$onto^0"||die"could not detach HEAD"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:31
Remove the call to the pre-rebase hook from
git-rebase--interactive.sh and rely on the call in
git-rebase.sh.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 14 --------------
git-rebase.sh | 12 +++++++-----
2 files changed, 7 insertions(+), 19 deletions(-)
@@ -753,8 +741,6 @@ esac gitvarGIT_COMMITTER_IDENT>/dev/null||die"You need to set your committer info first"-run_pre_rebase_hook"$upstream_arg""$@"- comment_for_reflogstartiftest!-z"$switch_to"
@@ -513,15 +513,15 @@ orig_head=$branch require_clean_work_tree"rebase""Please commit or stash them."-test"$type"=interactive&&run_interactive_rebase"$@"-# Now we are rebasing commits $upstream..$branch (or with --root,# everything leading up to $branch) on top of $onto# Check if we are already based on $onto with linear history,-# but this should be done only when upstream and onto are the same.+# but this should be done only when upstream and onto are the same+# and if this is not an interactive rebase.mb=$(gitmerge-base"$onto""$branch")-iftest"$upstream"="$onto"&&test"$mb"="$onto"&&+iftest"$type"!=interactive&&test"$upstream"="$onto"&&+test"$mb"="$onto"&&# linear history?!(gitrev-list--parents"$onto".."$branch"|sane_grep" .* ")>/dev/nullthen
@@ -539,6 +539,8 @@ fi# If a hook exists, give it a chance to interrupt run_pre_rebase_hook"$upstream_arg""$@"+test"$type"=interactive&&run_interactive_rebase+# Detach HEAD and reset the tree say"First, rewinding head to replay your work on top of it..." gitcheckout-q"$onto^0"||die"could not detach HEAD"
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:31
Remove the check for clean work tree from git-rebase--interactive.sh and
rely on the check in git-rebase.sh.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 2 --
git-rebase.sh | 4 ++--
2 files changed, 2 insertions(+), 4 deletions(-)
@@ -753,8 +753,6 @@ esac gitvarGIT_COMMITTER_IDENT>/dev/null||die"You need to set your committer info first"-require_clean_work_tree"rebase""Please commit or stash them."- run_pre_rebase_hook"$upstream_arg""$@" comment_for_reflogstart
@@ -511,10 +511,10 @@ case "$#" inesacorig_head=$branch-test"$type"=interactive&&run_interactive_rebase"$@"- require_clean_work_tree"rebase""Please commit or stash them."+test"$type"=interactive&&run_interactive_rebase"$@"+# Now we are rebasing commits $upstream..$branch (or with --root,# everything leading up to $branch) on top of $onto
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:31
Extract the code for merge-based rebase to git-rebase--merge.sh.
Suggested-by: Johannes Sixt <redacted>
Signed-off-by: Martin von Zweigbergk <redacted>
---
Changes since v1:
* As suggested by Johannes Sixt, git-rebase--$type is now sourced
instead of executed.
What copyright year? Most of the code is just extracted from
git-rebase.sh, which has copyright year 2005. Does that matter?
Would read_initial_state be a better name than read_basic_state?
.gitignore | 1 +
Makefile | 1 +
git-rebase--merge.sh | 154 +++++++++++++++++++++++++++++++++++++++++++++++
git-rebase.sh | 162 ++++----------------------------------------------
4 files changed, 167 insertions(+), 151 deletions(-)
create mode 100644 git-rebase--merge.sh
@@ -0,0 +1,154 @@+#!/bin/sh+#+# Copyright (c) 2010 Junio C Hamano.+#++.git-sh-setup++prec=4++read_state(){+onto_name=$(cat"$state_dir"/onto_name)&&+end=$(cat"$state_dir"/end)&&+msgnum=$(cat"$state_dir"/msgnum)+}++continue_merge(){+test-d"$state_dir"||die"$state_dir directory does not exist"++unmerged=$(gitls-files-u)+iftest-n"$unmerged"+then+echo"You still have unmerged paths in your index"+echo"did you forget to use git add?"+die"$resolvemsg"+fi++cmt=`cat"$state_dir/current"`+if!gitdiff-index--quiet--ignore-submodulesHEAD--+then+if!gitcommit--no-verify-C"$cmt"+then+echo"Commit failed, please do not call \"git commit\""+echo"directly, but instead do one of the following: "+die"$resolvemsg"+fi+iftest-z"$GIT_QUIET"+then+printf"Committed: %0${prec}d "$msgnum+fi+echo"$cmt$(gitrev-parseHEAD^0)">>"$state_dir/rewritten"+else+iftest-z"$GIT_QUIET"+then+printf"Already applied: %0${prec}d "$msgnum+fi+fi+test-z"$GIT_QUIET"&&+GIT_PAGER=''gitlog--format=%s-1"$cmt"++# onto the next patch:+msgnum=$(($msgnum+1))+echo"$msgnum">"$state_dir/msgnum"+}++call_merge(){+cmt="$(cat"$state_dir/cmt.$1")"+echo"$cmt">"$state_dir/current"+hd=$(gitrev-parse--verifyHEAD)+cmt_name=$(gitsymbolic-refHEAD2>/dev/null||echoHEAD)+msgnum=$(cat"$state_dir/msgnum")+evalGITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'+evalGITHEAD_$hd='$onto_name'+exportGITHEAD_$cmtGITHEAD_$hd+iftest-n"$GIT_QUIET"+then+GIT_MERGE_VERBOSITY=1&&exportGIT_MERGE_VERBOSITY+fi+test-z"$strategy"&&strategy=recursive+eval'git-merge-$strategy'$strategy_opts'"$cmt^" -- "$hd" "$cmt"'+rv=$?+case"$rv"in+0)+unsetGITHEAD_$cmtGITHEAD_$hd+return+;;+1)+gitrerere$allow_rerere_autoupdate+die"$resolvemsg"+;;+2)+echo"Strategy: $rv$strategy failed, try another"1>&2+die"$resolvemsg"+;;+*)+die"Unknown exit code ($rv) from command:"\+"git-merge-$strategy$cmt^ -- HEAD $cmt"+;;+esac+}++finish_rb_merge(){+move_to_original_branch+gitnotescopy--for-rewrite=rebase<"$state_dir"/rewritten+iftest-x"$GIT_DIR"/hooks/post-rewrite&&+test-s"$state_dir"/rewritten;then+"$GIT_DIR"/hooks/post-rewriterebase<"$state_dir"/rewritten+fi+rm-r"$state_dir"+sayAlldone.+}++case"$action"in+continue)+read_state+continue_merge+whiletest"$msgnum"-le"$end"+do+call_merge"$msgnum"+continue_merge+done+finish_rb_merge+exit+;;+skip)+read_state+gitrerereclear+msgnum=$(($msgnum+1))+whiletest"$msgnum"-le"$end"+do+call_merge"$msgnum"+continue_merge+done+finish_rb_merge+exit+;;+esac++mkdir-p"$state_dir"+echo"$onto_name">"$state_dir/onto_name"+echo"$head_name">"$state_dir/head-name"+echo"$onto">"$state_dir/onto"+echo"$orig_head">"$state_dir/orig-head"+echo"$GIT_QUIET">"$state_dir/quiet"++msgnum=0+forcmtin`gitrev-list--reverse--no-merges"$revisions"`+do+msgnum=$(($msgnum+1))+echo"$cmt">"$state_dir/cmt.$msgnum"+done++echo1>"$state_dir/msgnum"+echo$msgnum>"$state_dir/end"++end=$msgnum+msgnum=1++whiletest"$msgnum"-le"$end"+do+call_merge"$msgnum"+continue_merge+done++finish_rb_merge
@@ -68,94 +67,13 @@ preserve_merges=autosquash=test"$(gitconfig--boolrebase.autosquash)"="true"&&autosquash=t-read_state(){-iftest"$type"=merge-then-onto_name=$(cat"$state_dir"/onto_name)&&-end=$(cat"$state_dir"/end)&&-msgnum=$(cat"$state_dir"/msgnum)-fi&&+read_basic_state(){head_name=$(cat"$state_dir"/head-name)&&onto=$(cat"$state_dir"/onto)&&orig_head=$(cat"$state_dir"/orig-head)&&GIT_QUIET=$(cat"$state_dir"/quiet)}-continue_merge(){-test-d"$merge_dir"||die"$merge_dir directory does not exist"--unmerged=$(gitls-files-u)-iftest-n"$unmerged"-then-echo"You still have unmerged paths in your index"-echo"did you forget to use git add?"-die"$resolvemsg"-fi--cmt=`cat"$merge_dir/current"`-if!gitdiff-index--quiet--ignore-submodulesHEAD---then-if!gitcommit--no-verify-C"$cmt"-then-echo"Commit failed, please do not call \"git commit\""-echo"directly, but instead do one of the following: "-die"$resolvemsg"-fi-iftest-z"$GIT_QUIET"-then-printf"Committed: %0${prec}d "$msgnum-fi-echo"$cmt$(gitrev-parseHEAD^0)">>"$merge_dir/rewritten"-else-iftest-z"$GIT_QUIET"-then-printf"Already applied: %0${prec}d "$msgnum-fi-fi-test-z"$GIT_QUIET"&&-GIT_PAGER=''gitlog--format=%s-1"$cmt"--# onto the next patch:-msgnum=$(($msgnum+1))-echo"$msgnum">"$merge_dir/msgnum"-}--call_merge(){-cmt="$(cat"$merge_dir/cmt.$1")"-echo"$cmt">"$merge_dir/current"-hd=$(gitrev-parse--verifyHEAD)-cmt_name=$(gitsymbolic-refHEAD2>/dev/null||echoHEAD)-msgnum=$(cat"$merge_dir/msgnum")-evalGITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'-evalGITHEAD_$hd='$onto_name'-exportGITHEAD_$cmtGITHEAD_$hd-iftest-n"$GIT_QUIET"-then-GIT_MERGE_VERBOSITY=1&&exportGIT_MERGE_VERBOSITY-fi-test-z"$strategy"&&strategy=recursive-eval'git-merge-$strategy'$strategy_opts'"$cmt^" -- "$hd" "$cmt"'-rv=$?-case"$rv"in-0)-unsetGITHEAD_$cmtGITHEAD_$hd-return-;;-1)-gitrerere$allow_rerere_autoupdate-die"$resolvemsg"-;;-2)-echo"Strategy: $rv$strategy failed, try another"1>&2-die"$resolvemsg"-;;-*)-die"Unknown exit code ($rv) from command:"\-"git-merge-$strategy$cmt^ -- HEAD $cmt"-;;-esac-}- move_to_original_branch(){case"$head_name"inrefs/*)
@@ -341,7 +248,7 @@ test $# -gt 2 && usageiftest-n"$action"thentest-z"$in_progress"&&die"No rebase in progress?"-test"$type"=interactive&&run_interactive_rebase+test"$type"=interactive&&run_specific_rebaseficase"$action"in
@@ -352,44 +259,23 @@ continue)echo"mark them as resolved using git add"exit1}-read_state-iftest-d"$merge_dir"-then-continue_merge-whiletest"$msgnum"-le"$end"-do-call_merge"$msgnum"-continue_merge-done-finish_rb_merge-exit-fi+read_basic_state+run_specific_rebasegitam--resolved--3way--resolvemsg="$resolvemsg"&&move_to_original_branchexit;; skip)gitreset--hardHEAD||exit$?-read_state-iftest-d"$merge_dir"-then-gitrerereclear-msgnum=$(($msgnum+1))-whiletest"$msgnum"-le"$end"-do-call_merge"$msgnum"-continue_merge-done-finish_rb_merge-exit-fi+read_basic_state+run_specific_rebasegitam-3--skip--resolvemsg="$resolvemsg"&&move_to_original_branchexit;; abort)gitrerereclear-read_state+read_basic_statecase"$head_name"inrefs/*)gitsymbolic-refHEAD$head_name||
@@ -548,7 +434,7 @@ thenGIT_PAGER=''gitdiff--stat--summary"$mb""$onto"fi-test"$type"=interactive&&run_interactive_rebase+test"$type"=interactive&&run_specific_rebase# Detach HEAD and reset the tree say"First, rewinding head to replay your work on top of it..."
@@ -590,30 +476,4 @@ fi# start doing a rebase with git-merge# this is rename-aware if the recursive (default) strategy is used-mkdir-p"$merge_dir"-echo"$onto_name">"$merge_dir/onto_name"-echo"$head_name">"$merge_dir/head-name"-echo"$onto">"$merge_dir/onto"-echo"$orig_head">"$merge_dir/orig-head"-echo"$GIT_QUIET">"$merge_dir/quiet"--msgnum=0-forcmtin`gitrev-list--reverse--no-merges"$revisions"`-do-msgnum=$(($msgnum+1))-echo"$cmt">"$merge_dir/cmt.$msgnum"-done--echo1>"$merge_dir/msgnum"-echo$msgnum>"$merge_dir/end"--end=$msgnum-msgnum=1--whiletest"$msgnum"-le"$end"-do-call_merge"$msgnum"-continue_merge-done--finish_rb_merge+run_specific_rebase
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:31
The variables $branch and $orig_head were used as synonyms. To avoid
confusion, remove $branch. The name 'orig_head' seems more suitable,
since that is the name used when the variable is persisted.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase.sh | 19 +++++++++----------
1 files changed, 9 insertions(+), 10 deletions(-)
@@ -485,10 +485,10 @@ case "$#" inswitch_to="$1"ifgitshow-ref--verify--quiet--"refs/heads/$1"&&-branch=$(gitrev-parse-q--verify"refs/heads/$1")+orig_head=$(gitrev-parse-q--verify"refs/heads/$1")thenhead_name="refs/heads/$1"-elifbranch=$(gitrev-parse-q--verify"$1")+eliforig_head=$(gitrev-parse-q--verify"$1")thenhead_name="detached HEAD"else
@@ -506,24 +506,23 @@ case "$#" inhead_name="detached HEAD"branch_name=HEAD;# detachedfi-branch=$(gitrev-parse--verify"${branch_name}^0")||exit+orig_head=$(gitrev-parse--verify"${branch_name}^0")||exit;;esac-orig_head=$branch require_clean_work_tree"rebase""Please commit or stash them."-# Now we are rebasing commits $upstream..$branch (or with --root,-# everything leading up to $branch) on top of $onto+# Now we are rebasing commits $upstream..$orig_head (or with --root,+# everything leading up to $orig_head) on top of $onto# Check if we are already based on $onto with linear history,# but this should be done only when upstream and onto are the same# and if this is not an interactive rebase.-mb=$(gitmerge-base"$onto""$branch")+mb=$(gitmerge-base"$onto""$orig_head")iftest"$type"!=interactive&&test"$upstream"="$onto"&&test"$mb"="$onto"&&# linear history?-!(gitrev-list--parents"$onto".."$branch"|sane_grep" .* ")>/dev/null+!(gitrev-list--parents"$onto".."$orig_head"|sane_grep" .* ")>/dev/nulltheniftest-z"$force_rebase"then
@@ -554,11 +553,11 @@ test "$type" = interactive && run_interactive_rebase# Detach HEAD and reset the tree say"First, rewinding head to replay your work on top of it..." gitcheckout-q"$onto^0"||die"could not detach HEAD"-gitupdate-refORIG_HEAD$branch+gitupdate-refORIG_HEAD$orig_head# If the $onto is a proper descendant of the tip of the branch, then# we just fast-forwarded.-iftest"$mb"="$branch"+iftest"$mb"="$orig_head"thensay"Fast-forwarded $branch_name to $onto_name."move_to_original_branch
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:31
When rebase stops due to conflict, interactive rebase currently
displays a different hint to the user than non-interactive rebase
does. Use the same message for both types of rebase.
Signed-off-by: Martin von Zweigbergk <redacted>
---
Should we include the "mark the corrected paths with 'git add
<paths>'" part?
git-rebase--interactive.sh | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
From: Martin von Zweigbergk <hidden> Date: 2016-06-15 22:50:31
Rename variables HEAD and OLDHEAD to orig_head and HEADNAME to
head_name, which are the names used in git-rebase.sh. This prepares
for factoring out of the code that persists these variables during the
entire rebase process. Using the same variable names to mean the same
thing in both files also makes the code easier to read.
While at it, also remove the DOTEST variable and use the state_dir
variable that was inherited from git-rebase.sh instead.
Signed-off-by: Martin von Zweigbergk <redacted>
---
git-rebase--interactive.sh | 120 +++++++++++++++++++++----------------------
1 files changed, 59 insertions(+), 61 deletions(-)
@@ -12,22 +12,20 @@ .git-sh-setup-dotest="$GIT_DIR/rebase-merge"-# The file containing rebase commands, comments, and empty lines.# This file is created by "git rebase -i" then edited by the user. As# the lines are processed, they are removed from the front of this# file and written to the tail of $done.-todo="$dotest"/git-rebase-todo+todo="$state_dir"/git-rebase-todo# The rebase command lines that have already been processed. A line# is moved here when it is first handled, before any associated user# actions.-done="$dotest"/done+done="$state_dir"/done# The commit message that is planned to be used for any changes that# need to be committed following a user interaction.-msg="$dotest"/message+msg="$state_dir"/message# The file into which is accumulated the suggested commit message for# squash/fixup commands. When the first of a series of squash/fixups
@@ -42,14 +40,14 @@ msg="$dotest"/message# written to the file so far (including the initial "pick" commit).# Each time that a commit message is processed, this line is read and# updated. It is deleted just before the combined commit is made.-squash_msg="$dotest"/message-squash+squash_msg="$state_dir"/message-squash# If the current series of squash/fixups has not yet included a squash# command, then this file exists and holds the commit message of the# original "pick" commit. (If the series ends without a "squash"# command, then this can be used as the commit message of the combined# commit without opening the editor.)-fixup_msg="$dotest"/message-fixup+fixup_msg="$state_dir"/message-fixup# $rewritten is the name of a directory containing files for each# commit that is reachable by at least one merge base of $head and
@@ -57,14 +55,14 @@ fixup_msg="$dotest"/message-fixup# might be. This ensures that commits on merged, but otherwise# unrelated side branches are left alone. (Think "X" in the man page's# example.)-rewritten="$dotest"/rewritten+rewritten="$state_dir"/rewritten-dropped="$dotest"/dropped+dropped="$state_dir"/dropped# A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and# GIT_AUTHOR_DATE that will be used for the commit that is currently# being rebased.-author_script="$dotest"/author-script+author_script="$state_dir"/author-script# When an "edit" rebase command is being processed, the SHA1 of the# commit to be edited is recorded in this file. When "git rebase
@@ -72,14 +70,14 @@ author_script="$dotest"/author-script# will be amended to the HEAD commit, but only provided the HEAD# commit is still the commit to be edited. When any other rebase# command is processed, this file is deleted.-amend="$dotest"/amend+amend="$state_dir"/amend# For the post-rewrite hook, we make a list of rewritten commits and# their new sha1s. The rewritten-pending list keeps the sha1s of# commits that have been processed, but not committed yet,# e.g. because they are waiting for a 'squash' command.-rewritten_list="$dotest"/rewritten-list-rewritten_pending="$dotest"/rewritten-pending+rewritten_list="$state_dir"/rewritten-list+rewritten_pending="$state_dir"/rewritten-pendingGIT_CHERRY_PICK_HELP="$resolvemsg"exportGIT_CHERRY_PICK_HELP
@@ -205,20 +203,20 @@ pick_one_preserving_merges () {esacsha1=$(gitrev-parse$sha1)-iftest-f"$dotest"/current-commit+iftest-f"$state_dir"/current-committheniftest"$fast_forward"=tthenwhilereadcurrent_commitdogitrev-parseHEAD>"$rewritten"/$current_commit-done<"$dotest"/current-commit-rm"$dotest"/current-commit||+done<"$state_dir"/current-commit+rm"$state_dir"/current-commit||die"Cannot write current commit's replacement sha1"fifi-echo$sha1>>"$dotest"/current-commit+echo$sha1>>"$state_dir"/current-commit# rewrite parents; if none were rewritten, we can fast-forward.new_parents=
@@ -425,7 +423,7 @@ do_next () {mark_action_donepick_one$sha1||die_with_patch$sha1"Could not apply $sha1... $rest"-echo"$sha1">"$dotest"/stopped-sha+echo"$sha1">"$state_dir"/stopped-shamake_patch$sha1gitrev-parse--verifyHEAD>"$amend"warn"Stopped at $sha1... $rest"
@@ -490,7 +488,7 @@ do_next () {printf'Executing: %s\n'"$rest"# "exec" command doesn't take a sha1 in the todo-list.# => can't just use $sha1 here.-gitrev-parse--verifyHEAD>"$dotest"/stopped-sha+gitrev-parse--verifyHEAD>"$state_dir"/stopped-sha${SHELL:-@SHELL_PATH@}-c"$rest"# Actual executionstatus=$?iftest"$status"-ne0
@@ -549,9 +547,9 @@ do_next () {"$GIT_DIR"/hooks/post-rewriterebase<"$rewritten_list"true# we don't care if this hook failedfi&&-rm-rf"$dotest"&&+rm-rf"$state_dir"&&gitgc--auto&&-warn"Successfully rebased and updated $headname."+warn"Successfully rebased and updated $head_name."exit}
@@ -602,9 +600,9 @@ skip_unnecessary_picks () { get_saved_options(){test-d"$rewritten"&&preserve_merges=t-test-f"$dotest"/strategy&&strategy="$(cat"$dotest"/strategy)"-test-f"$dotest"/verbose&&verbose=t-test-f"$dotest"/rebase-root&&rebase_root=t+test-f"$state_dir"/strategy&&strategy="$(cat"$state_dir"/strategy)"+test-f"$state_dir"/verbose&&verbose=t+test-f"$state_dir"/rebase-root&&rebase_root=t}# Rearrange the todo list that has both "pick sha1 msg" and
@@ -704,7 +702,7 @@ first and then run 'git rebase --continue' again."}fi-record_in_rewritten"$(cat"$dotest"/stopped-sha)"+record_in_rewritten"$(cat"$state_dir"/stopped-sha)"require_clean_work_tree"rebase"do_rest
@@ -747,28 +745,28 @@ thendie"Could not checkout $switch_to"fi-head=$(gitrev-parse--verifyHEAD)||die"No HEAD?"-mkdir"$dotest"||die"Could not create temporary $dotest"+orig_head=$(gitrev-parse--verifyHEAD)||die"No HEAD?"+mkdir"$state_dir"||die"Could not create temporary $state_dir"-:>"$dotest"/interactive||die"Could not mark as interactive"-echo"$head_name">"$dotest"/head-name+:>"$state_dir"/interactive||die"Could not mark as interactive"+echo"$head_name">"$state_dir"/head-name-echo$head>"$dotest"/head+echo$orig_head>"$state_dir"/headcase"$rebase_root"in'')-rm-f"$dotest"/rebase-root;;+rm-f"$state_dir"/rebase-root;; *)-:>"$dotest"/rebase-root;;+:>"$state_dir"/rebase-root;;esac-echo$onto>"$dotest"/onto-test-z"$strategy"||echo"$strategy">"$dotest"/strategy-testt="$verbose"&&:>"$dotest"/verbose+echo$onto>"$state_dir"/onto+test-z"$strategy"||echo"$strategy">"$state_dir"/strategy+testt="$verbose"&&:>"$state_dir"/verboseiftestt="$preserve_merges"theniftest-z"$rebase_root"thenmkdir"$rewritten"&&-forcin$(gitmerge-base--all$head$upstream)+forcin$(gitmerge-base--all$orig_head$upstream)doecho$onto>"$rewritten"/$c||die"Could not init rewritten commits"
@@ -782,21 +780,21 @@ then# parents to rewrite and skipping dropped commits would# prematurely end our probemerges_option=-first_after_upstream="$(gitrev-list--reverse--first-parent$upstream..$head|head-n1)"+first_after_upstream="$(gitrev-list--reverse--first-parent$upstream..$orig_head|head-n1)"elsemerges_option="--no-merges --cherry-pick"fi-shorthead=$(gitrev-parse--short$head)+shorthead=$(gitrev-parse--short$orig_head)shortonto=$(gitrev-parse--short$onto)iftest-z"$rebase_root"# this is now equivalent to ! -z "$upstream"thenshortupstream=$(gitrev-parse--short$upstream)-revisions=$upstream...$head+revisions=$upstream...$orig_headshortrevisions=$shortupstream..$shortheadelse-revisions=$onto...$head+revisions=$onto...$orig_headshortrevisions=$shortheadfi gitrev-list$merges_option--pretty=oneline--abbrev-commit\
@@ -837,13 +835,13 @@ thenmkdir"$dropped"# Save all non-cherry-picked changesgitrev-list$revisions--left-right--cherry-pick|\-sed-n"s/^>//p">"$dotest"/not-cherry-picks+sed-n"s/^>//p">"$state_dir"/not-cherry-picks# Now all commits and note which ones are missing in# not-cherry-picks and hence being droppedgitrev-list$revisions|whilereadrevdo-iftest-f"$rewritten"/$rev-a"$(sane_grep"$rev""$dotest"/not-cherry-picks)"=""+iftest-f"$rewritten"/$rev-a"$(sane_grep"$rev""$state_dir"/not-cherry-picks)"=""then# Use -f2 because if rev-list is telling us this commit is# not worthwhile, we don't want to track its multiple heads,