{"thread":{"id":"14239","subject":"git sequencer prototype","startedAt":"2008-07-01T02:38:30Z","lastAt":"2008-07-09T05:20:52Z","messageCount":52,"participants":["Stephan Beyer","Junio C Hamano","Jakub Narebski","Johannes Schindelin","Alex Riesen","Thomas Adam","Karl Hasselström"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"81823","messageId":"1214879914-17866-1-git-send-email-s-beyer@gmx.net","threadId":"14239","inReplyTo":null,"subject":"git sequencer prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-01T02:38:30Z","receivedAt":"2008-07-01T02:38:30Z","isPatch":false,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nhere is the patchset for the git-sequencer prototype, documentation,\ntest suite and a first git-am and git-rebase-i migration.\nIndeed, monster patches. ;)\n\nI'm using sequencer-based git-am and git-rebase-i and also git-sequencer\nitself for around 2-3 weeks now. So, for me, it is reality-proven, but\nI'm curious about your opinions/suggestions in usage and source.\n\nThe migration patches are a little hard to code-review in the diff-form,\nbut feel free to apply, test, and then look at the code ;)\n\nRegards,\n  Stephan\n"},{"id":"81827","messageId":"1214879914-17866-2-git-send-email-s-beyer@gmx.net","threadId":"14239","inReplyTo":"1214879914-17866-1-git-send-email-s-beyer@gmx.net","subject":"[RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-01T02:38:31Z","receivedAt":"2008-07-01T02:38:31Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"git sequencer is planned as a backend for user scripts\nthat execute a sequence of git instructions and perhaps\nneed manual intervention, for example git-rebase or git-am.\n\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nMentored-by: Daniel Barkalow <barkalow@iabervon.org>\nSigned-off-by: Stephan Beyer <s-beyer@gmx.net>\n---\nSome comments:\n - It's declared as plumbing, but the prototype can't really be\n   named \"plumbing\", imho, since it uses porcelain like git-commit.\n - I hope it is obvious that parts of it are based on\n   git-rebase-i and git-am code, so if you stumble over code\n   that looks familiar, it is not necessarily by accident.\n\n .gitignore       |    1 +\n Makefile         |    1 +\n command-list.txt |    1 +\n git-sequencer.sh | 1902 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 4 files changed, 1905 insertions(+), 0 deletions(-)\n create mode 100755 git-sequencer.sh\n\ndiff --git a/.gitignore b/.gitignore\nindex 4ff2fec..65a075b 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -111,6 +111,7 @@ git-revert\n git-rm\n git-send-email\n git-send-pack\n+git-sequencer\n git-sh-setup\n git-shell\n git-shortlog\ndiff --git a/Makefile b/Makefile\nindex bf77292..db93956 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -250,6 +250,7 @@ SCRIPT_SH += git-rebase--interactive.sh\n SCRIPT_SH += git-rebase.sh\n SCRIPT_SH += git-repack.sh\n SCRIPT_SH += git-request-pull.sh\n+SCRIPT_SH += git-sequencer.sh\n SCRIPT_SH += git-sh-setup.sh\n SCRIPT_SH += git-stash.sh\n SCRIPT_SH += git-submodule.sh\ndiff --git a/command-list.txt b/command-list.txt\nindex 3583a33..44bb5b0 100644\n--- a/command-list.txt\n+++ b/command-list.txt\n@@ -101,6 +101,7 @@ git-rev-parse                           ancillaryinterrogators\n git-rm                                  mainporcelain common\n git-send-email                          foreignscminterface\n git-send-pack                           synchingrepositories\n+git-sequencer                           plumbingmanipulators\n git-shell                               synchelpers\n git-shortlog                            mainporcelain\n git-show                                mainporcelain common\ndiff --git a/git-sequencer.sh b/git-sequencer.sh\nnew file mode 100755\nindex 0000000..31b0568\n--- /dev/null\n+++ b/git-sequencer.sh\n@@ -0,0 +1,1902 @@\n+#!/bin/sh\n+# A git sequencer prototype.\n+\n+SUBDIRECTORY_OK=Yes\n+OPTIONS_KEEPDASHDASH=\n+OPTIONS_SPEC=\"\\\n+git-sequencer [options] [--] [<file>]\n+git-sequencer (--continue | --abort | --skip | --edit | --status)\n+--\n+ Options to start a sequencing process\n+B,batch        run in batch-mode\n+onto=          checkout the given commit or branch first\n+q,quiet        suppress output\n+v,verbose      be more verbose\n+ Options to restart/change a sequencing process or show information\n+continue       continue paused sequencer process\n+abort          restore original branch and abort\n+skip           skip current patch and continue\n+status         show the status of the sequencing process\n+edit           invoke editor to let user edit the remaining insns\n+ Options to be used by user scripts\n+caller=        provide information string: name|abort|cont|skip\n+\"\n+\n+. git-sh-setup\n+require_work_tree\n+\n+git var GIT_COMMITTER_IDENT >/dev/null ||\n+\tdie 'You need to set your committer info first'\n+\n+SEQ_DIR=\"$GIT_DIR/sequencer\"\n+TODO=\"$SEQ_DIR/todo\"\n+DONE=\"$SEQ_DIR/done\"\n+MSG=\"$SEQ_DIR/message\"\n+PATCH=\"$SEQ_DIR/patch\"\n+AUTHOR_SCRIPT=\"$SEQ_DIR/author-script\"\n+ORIG_AUTHOR_SCRIPT=\"$SEQ_DIR/author-script.orig\"\n+CALLER_SCRIPT=\"$SEQ_DIR/caller-script\"\n+WHY_FILE=\"$SEQ_DIR/why\"\n+MARK_PREFIX='refs/sequencer-marks'\n+\n+warn () {\n+\techo \"$*\" >&2\n+}\n+\n+cleanup () {\n+\tfor ref in $(git for-each-ref --format='%(refname)' \"$MARK_PREFIX\")\n+\tdo\n+\t\tgit update-ref -d \"$ref\" \"$ref\" || return\n+\tdone\n+\trm -rf \"$SEQ_DIR\"\n+}\n+\n+# Die if there has been a conflict\n+die_to_continue () {\n+\twarn \"$*\"\n+\ttest -z \"$BATCHMODE\" ||\n+\t\tdie_abort 'Aborting, because of batch mode.'\n+\ttest -z \"$WHY\" &&\n+\t\techo 'conflict' >\"$WHY_FILE\" ||\n+\t\techo \"$WHY\" >\"$WHY_FILE\"\n+\texit 3\n+}\n+\n+die_abort () {\n+\trestore\n+\tcleanup\n+\tdie \"$1\"\n+}\n+\n+quit () {\n+\tcleanup\n+\ttest -z \"$*\" ||\n+\t\techo \"$*\"\n+\texit 0\n+}\n+\n+output () {\n+\tcase \"$VERBOSE\" in\n+\t0)\n+\t\t\"$@\" >/dev/null\n+\t\t;;\n+\t1)\n+\t\toutput=$(\"$@\" 2>&1 )\n+\t\tstatus=$?\n+\t\ttest $status -ne 0 && printf '%s\\n' \"$output\"\n+\t\treturn $status\n+\t\t;;\n+\t2)\n+\t\t\"$@\"\n+\t\t;;\n+\tesac\n+}\n+\n+require_clean_work_tree () {\n+\t# test if working tree is dirty\n+\tgit rev-parse --verify HEAD >/dev/null &&\n+\tgit update-index --ignore-submodules --refresh &&\n+\tgit diff-files --quiet --ignore-submodules &&\n+\tgit diff-index --cached --quiet HEAD --ignore-submodules -- ||\n+\tdie 'Working tree is dirty'\n+}\n+\n+ORIG_REFLOG_ACTION=\"$GIT_REFLOG_ACTION\"\n+\n+comment_for_reflog () {\n+\tif test -z \"$ORIG_REFLOG_ACTION\"\n+\tthen\n+\t\tGIT_REFLOG_ACTION='sequencer'\n+\t\ttest -z \"$CALLER\" ||\n+\t\t\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION ($CALLER)\"\n+\t\texport GIT_REFLOG_ACTION\n+\tfi\n+}\n+\n+# Get commit message from commit $1\n+commit_message () {\n+\tgit cat-file commit \"$1\" | sed -e '1,/^$/d'\n+}\n+\n+LAST_COUNT=\n+mark_action_done () {\n+\tsed -e 1q <\"$TODO\" >>\"$DONE\"\n+\tsed -e 1d <\"$TODO\" >\"$TODO.new\"\n+\tmv -f \"$TODO.new\" \"$TODO\"\n+\tif test \"$VERBOSE\" -gt 0\n+\tthen\n+\t\tcount=$(grep -c '^[^#]' <\"$DONE\")\n+\t\ttotal=$(expr \"$count\" + \"$(grep -c '^[^#]' <\"$TODO\")\")\n+\t\tif test \"$LAST_COUNT\" != \"$count\"\n+\t\tthen\n+\t\t\tLAST_COUNT=\"$count\"\n+\t\t\ttest \"$VERBOSE\" -lt 1 ||\n+\t\t\t\tprintf 'Sequencing (%d/%d)\\r' \"$count\" \"$total\"\n+\t\t\ttest \"$VERBOSE\" -lt 2 || echo\n+\t\tfi\n+\tfi\n+}\n+\n+# Generate message, patch and author script files\n+make_patch () {\n+\tparent_sha1=$(git rev-parse --verify \"$1\"^) ||\n+\t\tdie \"Cannot get patch for $1^\"\n+\tgit diff-tree -p \"$parent_sha1..$1\" >\"$PATCH\"\n+\ttest -f \"$MSG\" ||\n+\t\tcommit_message \"$1\" >\"$MSG\"\n+\ttest -f \"$AUTHOR_SCRIPT\" ||\n+\t\tget_author_ident_from_commit \"$1\" >\"$AUTHOR_SCRIPT\"\n+}\n+\n+# Generate a patch and die with \"conflict\" status code\n+die_with_patch () {\n+\tmake_patch \"$1\"\n+\tgit rerere\n+\tdie_to_continue \"$2\"\n+}\n+\n+restore () {\n+\tgit rerere clear\n+\n+\tHEADNAME=$(cat \"$SEQ_DIR/head-name\")\n+\tHEAD=$(cat \"$SEQ_DIR/head\")\n+\tcase $HEADNAME in\n+\trefs/*)\n+\t\tgit symbolic-ref HEAD \"$HEADNAME\"\n+\t\t;;\n+\tesac &&\n+\toutput git reset --hard \"$HEAD\"\n+}\n+\n+has_action () {\n+\tgrep '^[^#]' \"$1\" >/dev/null\n+}\n+\n+# Check if text file $1 contains a commit message\n+has_message () {\n+\ttest -n \"$(sed -n -e '/^Signed-off-by:/d;/^[^#]/p' <\"$1\")\"\n+}\n+\n+# Count parents of commit $1\n+count_parents() {\n+\tgit cat-file commit \"$1\" | sed -n -e '1,/^$/p' | grep -c '^parent'\n+}\n+\n+# Evaluate the author script to get author information to\n+# apply it with \"with_author git foo\" then.\n+get_current_author () {\n+\t. \"$AUTHOR_SCRIPT\" ||\n+\t\tdie_abort 'Author script is damaged. This must not happen!'\n+}\n+\n+# Run command with author information\n+with_author () {\n+\tGIT_AUTHOR_NAME=\"$GIT_AUTHOR_NAME\" \\\n+\tGIT_AUTHOR_EMAIL=\"$GIT_AUTHOR_EMAIL\" \\\n+\tGIT_AUTHOR_DATE=\"$GIT_AUTHOR_DATE\" \\\n+\t\t\"$@\"\n+}\n+\n+# Usage: pick_one (cherry-pick|revert) [-*|--edit] sha1\n+pick_one () {\n+\twhat=\"$1\"\n+\t# we just assume that this is either cherry-pick or revert\n+\tshift\n+\n+\t# check for fast-forward if no options are given\n+\tif expr \"x$1\" : 'x[^-]' >/dev/null\n+\tthen\n+\t\ttest \"$(git rev-parse --verify \"$1^\")\" = \\\n+\t\t\t\"$(git rev-parse --verify HEAD)\" &&\n+\t\t\toutput git reset --hard \"$1\" &&\n+\t\t\treturn\n+\tfi\n+\ttest \"$1\" != '--edit' -a \"$what\" = 'revert' &&\n+\t\twhat='revert --no-edit'\n+\ttest -n \"$SIGNOFF\" &&\n+\t\twhat=\"$what -s\"\n+\t$use_output git $what \"$@\"\n+}\n+\n+nth_string () {\n+\tcase \"$1\" in\n+\t*1[0-9]|*[04-9])\n+\t\techo \"$1th\"\n+\t\t;;\n+\t*1)\n+\t\techo \"$1st\"\n+\t\t;;\n+\t*2)\n+\t\techo \"$1nd\"\n+\t\t;;\n+\t*3)\n+\t\techo \"$1rd\"\n+\t\t;;\n+\tesac\n+}\n+\n+make_squash_message () {\n+\tif test -f \"$squash_msg\"\n+\tthen\n+\t\tcount=$(($(sed -n -e 's/^# This is [^0-9]*\\([1-9][0-9]*\\).*/\\1/p' \\\n+\t\t\t<\"$squash_msg\" | sed -n -e '$p')+1))\n+\t\techo \"# This is a combination of $count commits.\"\n+\t\tsed -e '1d' -e '2,/^./{\n+\t\t\t/^$/d\n+\t\t}' <\"$squash_msg\"\n+\telse\n+\t\tcount=2\n+\t\techo '# This is a combination of 2 commits.'\n+\t\techo '# The first commit message is:'\n+\t\techo\n+\t\tcommit_message HEAD\n+\tfi\n+\techo\n+\techo \"# This is the $(nth_string \"$count\") commit message:\"\n+\techo\n+\tcommit_message \"$1\"\n+}\n+\n+make_squash_message_multiple () {\n+\techo '# This is a dummy to get the 0.' >\"$squash_msg\"\n+\tfor cur_sha1 in $(git rev-list --reverse \"$sha1..HEAD\")\n+\tdo\n+\t\tmake_squash_message \"$cur_sha1\" >\"$MSG\"\n+\t\tcp \"$MSG\" \"$squash_msg\"\n+\tdone\n+}\n+\n+peek_next_command () {\n+\tsed -n -e '1s/ .*$//p' <\"$TODO\"\n+}\n+\n+# If $1 is a mark, make a ref from it; otherwise keep it\n+mark_to_ref () {\n+\targ=\"$1\"\n+\tref=$(expr \"x$arg\" : 'x:0*\\([0-9][0-9]*\\)$')\n+\ttest -n \"$ref\" &&\n+\t\targ=\"$MARK_PREFIX/$ref\"\n+\tprintf '%s\\n' \"$arg\"\n+}\n+\n+mark_to_commit () {\n+\tgit rev-parse --verify \"$(mark_to_ref \"$1\")\"\n+}\n+\n+\n+cannot_fallback () {\n+\techo \"$1\"\n+\tdie_to_continue 'Cannot fall back to three-way merge. Please hand-edit.'\n+}\n+\n+\n+fallback_3way () {\n+\tO_OBJECT=$(cd \"$GIT_OBJECT_DIRECTORY\" && pwd)\n+\n+\trm -fr \"$PATCH-merge-\"*\n+\tmkdir \"$PATCH-merge-tmp-dir\"\n+\n+\t# First see if the patch records the index info that we can use.\n+\tgit apply --build-fake-ancestor \"$PATCH-merge-tmp-index\" \"$PATCH\" &&\n+\tGIT_INDEX_FILE=\"$PATCH-merge-tmp-index\" \\\n+\t\tgit write-tree >\"$PATCH-merge-base+\" ||\n+\tcannot_fallback 'Repository lacks necessary blobs to fall back on 3-way merge.'\n+\n+\techo 'Using index info to reconstruct a base tree...'\n+\tif GIT_INDEX_FILE=\"$PATCH-merge-tmp-index\" \\\n+\t\tgit apply --cached \"$PATCH\"\n+\tthen\n+\t\tmv \"$PATCH-merge-base+\" \"$PATCH-merge-base\"\n+\t\tmv \"$PATCH-merge-tmp-index\" \"$PATCH-merge-index\"\n+\telse\n+\t\tcannot_fallback \"Did you hand edit your patch?\n+It does not apply to blobs recorded in its index.\"\n+\tfi\n+\n+\ttest -f \"$PATCH-merge-index\" &&\n+\this_tree=$(GIT_INDEX_FILE=\"$PATCH-merge-index\" git write-tree) &&\n+\torig_tree=$(cat \"$PATCH-merge-base\") &&\n+\trm -fr \"$PATCH-merge-\"* || exit 1\n+\n+\techo 'Falling back to patching base and 3-way merge...'\n+\n+\t# This is not so wrong.  Depending on which base we picked,\n+\t# orig_tree may be wildly different from ours, but his_tree\n+\t# has the same set of wildly different changes in parts the\n+\t# patch did not touch, so recursive ends up canceling them,\n+\t# saying that we reverted all those changes.\n+\n+\teval GITHEAD_$his_tree='\"$firstline\"'\n+\texport GITHEAD_$his_tree\n+\tgit-merge-recursive \"$orig_tree\" -- HEAD \"$his_tree\" || {\n+\t\tgit rerere\n+\t\tdie 'Failed to merge in the changes.'\n+\t}\n+}\n+\n+# Run hook \"$@\" (with arguments) if executable\n+run_hook () {\n+\ttest -z \"$1\" || return\n+\thookname=\"$1\"\n+\thook=\"$GIT_DIR/hooks/$hookname\"\n+\tshift\n+\tif test -x \"$hook\"\n+\tthen\n+\t\t\"$hook\" \"$@\" ||\n+\t\t\tdie_to_continue \"Hook $hookname failed.\"\n+\tfi\n+}\n+\n+# Add Signed-off-by: line if general option --signoff is given\n+dashdash_signoff () {\n+\tadd_signoff=\n+\tif test -n \"$SIGNOFF\"\n+\tthen\n+\t\tlast_signed_off_by=$(\n+\t\t\tsed -n -e '/^Signed-off-by: /p' <\"$MSG\" | sed -n -e '$p'\n+\t\t)\n+\t\ttest \"$last_signed_off_by\" = \"$SIGNOFF\" ||\n+\t\t\tadd_signoff=$(\n+\t\t\t\ttest '' = \"$last_signed_off_by\" && echo\n+\t\t\t\techo \"$SIGNOFF\"\n+\t\t\t)\n+\tfi\n+\t{\n+\t\ttest -s \"$MSG\" && cat \"$MSG\"\n+\t\ttest -n \"$add_signoff\" && echo \"$add_signoff\"\n+\t} >\"$MSG.new\"\n+\tmv \"$MSG.new\" \"$MSG\"\n+}\n+\n+\n+### --caller-related functions\n+\n+# Show string for caller invocation for --abort/--continue/--skip\n+print_caller_info () {\n+\tcase \"$1\" in\n+\t--abort)\n+\t\techo \"$CALLER_ABRT\"\n+\t\t;;\n+\t--continue)\n+\t\techo \"$CALLER_CONT\"\n+\t\t;;\n+\t--skip)\n+\t\techo \"$CALLER_SKIP\"\n+\t\t;;\n+\t*)\n+\t\twarn 'Internal error: Unknown print_caller argument!'\n+\t\t;;\n+\tesac\n+}\n+\n+# Print the program to invoke to (--)abort/continue/skip\n+print_caller() {\n+\tcaller_info=$(print_caller_info \"$1\")\n+\tif test -n \"$CALLERCOMPARE\" -a -n \"$caller_info\"\n+\tthen\n+\t\ttest -n \"$CALLER\" && printf \"$CALLER \"\n+\t\techo \"$caller_info\"\n+\telse\n+\t\techo \"git sequencer $1\"\n+\tfi\n+}\n+\n+# Test if --caller was set correctly\n+# $1 must be abort/continue/skip\n+test_caller () {\n+\tcaller_info=$(print_caller_info \"--$1\")\n+\ttest -n \"$CALLERCOMPARE\" -a \\\n+\t\t\"$CALLERCOMPARE\" != \"$CALLERSTRING\" -a \\\n+\t\t-n \"$caller_info\" &&\n+\t\tdie \"You must use '$CALLER $caller_info' to $1!\"\n+}\n+\n+# Generate $CALLER_SCRIPT file from \"git foo|--abort|--continue|--skip\"\n+# string $1\n+generate_caller_script () {\n+\techo \"$1\" | sed -e 's/^\\(.*\\)|\\(.*\\)|\\(.*\\)|\\(.*\\)$/\\\n+CALLERCOMPARE=\"\\0\"\\\n+CALLER=\"\\1\"\\\n+CALLER_ABRT=\"\\2\"\\\n+CALLER_CONT=\"\\3\"\\\n+CALLER_SKIP=\"\\4\"/' >\"$CALLER_SCRIPT\"\n+}\n+\n+# Run caller script and set GIT_CHERRY_PICK_HELP\n+assure_caller () {\n+\ttest -r \"$CALLER_SCRIPT\" &&\n+\t\t. \"$CALLER_SCRIPT\"\n+\n+\tGIT_CHERRY_PICK_HELP=\"\n+After resolving the conflicts, mark the corrected paths with\n+\tgit add <paths>\n+or\n+\tgit rm <paths>\n+and run\n+\t$(print_caller --continue)\n+Note, that your working tree must match the index.\"\n+\texport GIT_CHERRY_PICK_HELP\n+}\n+\n+\n+### Helpers for check_* functions:\n+\n+# Print a warning on todo checking\n+todo_warn () {\n+\tprintf 'Warning at line %d, %s: %s\\n' \"$line\" \"$command\" \"$*\"\n+}\n+\n+# Raise an error on todo checking\n+todo_error () {\n+\tprintf 'Error at line %d, %s: %s\\n' \"$line\" \"$command\" \"$*\"\n+\tretval=1\n+}\n+\n+# Test if $1 is a commit on todo checking\n+commit_check () {\n+\ttest \"$(git cat-file -t \"$1\" 2>/dev/null)\" = commit ||\n+\t\ttodo_error \"'$1' is not a commit.\"\n+}\n+\n+# A helper function to check if $1 is a an available mark during check_*\n+arg_is_mark_check () {\n+\tfor cur_mark in $available_marks\n+\tdo\n+\t\ttest \"$cur_mark\" -eq \"${1#:}\" && return\n+\tdone\n+\ttodo_error \"Mark $1 is not yet defined.\"\n+}\n+\n+# A helper function for check_* and mark usage:\n+# check if \"$1\" is a commit or a defined mark\n+arg_is_mark_or_commit_check () {\n+\tif expr \"x$1\" : 'x:[0-9][0-9]*$' >/dev/null\n+\tthen\n+\t\targ_is_mark_check \"$1\"\n+\telse\n+\t\tcommit_check \"$1\"\n+\tfi\n+}\n+\n+strategy_check () {\n+\tcase \"$1\" in\n+\tresolve|recursive|octopus|ours|subtree|theirs)\n+\t\treturn\n+\t\t;;\n+\tesac\n+\ttodo_warn \"Strategy '$1' not known.\"\n+}\n+\n+\n+### Author script functions\n+\n+clean_author_script () {\n+\tcat \"$ORIG_AUTHOR_SCRIPT\" >\"$AUTHOR_SCRIPT\"\n+}\n+\n+# Take \"Name <e-mail>\" in stdin and outputs author script\n+make_author_script_from_string () {\n+\tsed -e 's/^\\(.*\\) <\\(.*\\)>.*$/GIT_AUTHOR_NAME=\"\\1\"\\\n+GIT_AUTHOR_EMAIL=\"\\2\"\\\n+GIT_AUTHOR_DATE=/'\n+}\n+\n+\n+### General option functions (and options spec)\n+\n+OPTIONS_GENERAL=' General options:\n+author= Override author\n+C,reuse-commit= Reuse message and authorship data from commit\n+F,file= Take commit message from given file\n+m,message= Specify commit message\n+M,reuse-message= Reuse message from commit\n+signoff Add signoff\n+e,edit Invoke editor to edit commit message'\n+\n+# Check if option is a general option\n+check_general_option () {\n+\tgeneral_shift=1\n+\tcase \"$1\" in\n+\t--signoff)\n+\t\treturn 0\n+\t\t;;\n+\t--author)\n+\t\tgeneral_shift=2\n+\t\tauthor_opt=\"t$author_opt\"\n+\t\texpr \"x$2\" : 'x.* <.*>' >/dev/null ||\n+\t\t\ttodo_error \"Author \\\"$2\\\" not in the correct format \\\"Name <e-mail>\\\".\"\n+\t\t;;\n+\t-m)\n+\t\tgeneral_shift=2\n+\t\tmsg_opt=\"t$msg_opt\"\n+\t\t;;\n+\t-C)\n+\t\tgeneral_shift=2\n+\t\tmsg_opt=\"t$msg_opt\"\n+\t\tauthor_opt=\"t$author_opt\"\n+\t\tcommit_check \"$2\"\n+\t\t;;\n+\t-M)\n+\t\tgeneral_shift=2\n+\t\tmsg_opt=\"t$msg_opt\"\n+\t\tcommit_check \"$2\"\n+\t\t;;\n+\t-F)\n+\t\tgeneral_shift=2\n+\t\tmsg_opt=\"t$msg_opt\"\n+\t\ttest -r \"$2\" ||\n+\t\t\ttodo_error \"Cannot read file '$2'.\"\n+\t\t;;\n+\t-e)\n+\t\ttest -z \"$BATCHMODE\" ||\n+\t\t\ttodo_error '--batch and --edit options do not make sense together.'\n+\t\t;;\n+\t*)\n+\t\treturn 1\n+\t\t;;\n+\tesac\n+}\n+\n+# Set a general option variable or return 1\n+handle_general_option () {\n+\tgeneral_shift=1\n+\tcase \"$1\" in\n+\t--signoff)\n+\t\tSIGNOFF=$(git-var GIT_COMMITTER_IDENT | sed -e '\n+\t\t\t\ts/>.*/>/\n+\t\t\t\ts/^/Signed-off-by: /')\n+\t\t;;\n+\t--author)\n+\t\tgeneral_shift=2\n+\t\tAUTHOR=t\n+\t\techo \"$2\" |\n+\t\t\tmake_author_script_from_string >\"$AUTHOR_SCRIPT\"\n+\t\t;;\n+\t-m)\n+\t\tgeneral_shift=2\n+\t\tMESSAGE=\"$2\"\n+\t\t;;\n+\t-C)\n+\t\tgeneral_shift=2\n+\t\tAUTHOR=t\n+\t\tget_author_ident_from_commit \"$2\" >\"$AUTHOR_SCRIPT\"\n+\t\tMESSAGE=$(commit_message \"$2\")\n+\t\t;;\n+\t-M)\n+\t\tgeneral_shift=2\n+\t\tMESSAGE=$(commit_message \"$2\")\n+\t\t;;\n+\t-F)\n+\t\tgeneral_shift=2\n+\t\tMESSAGE=$(cat \"$2\")\n+\t\t;;\n+\t-e)\n+\t\tEDIT=--edit\n+\t\t;;\n+\t*)\n+\t\treturn 1\n+\t\t;;\n+\tesac\n+}\n+\n+\n+### Functions for checking and realizing TODO instructions\n+# Note that options_*, check_* and insn_* function names are reserved.\n+\n+options_pause=\"\\\n+pause\n+--\n+\"\n+\n+# Check the \"pause\" instruction\n+check_pause () {\n+\tshift\n+\ttest -z \"$BATCHMODE\" ||\n+\t\ttodo_error '\"pause\" instruction and --batch do not make sense together.'\n+\ttest $# -eq 0 ||\n+\t\ttodo_error 'The pause instruction takes no arguments.'\n+\treturn 0\n+}\n+\n+# Realize the \"pause\" instruction\n+insn_pause () {\n+\tmark_action_done\n+\tmake_patch HEAD\n+\tif test \"$VERBOSE\" -gt 0\n+\tthen\n+\t\twarn\n+\t\twarn 'You can now edit files and add them to the index.'\n+\t\twarn 'Once you are satisfied with your changes, run'\n+\t\twarn\n+\t\twarn \"\t$(print_caller --continue)\"\n+\t\twarn\n+\t\twarn 'If you only want to change the commit message, run'\n+\t\twarn 'git commit --amend before.'\n+\tfi\n+\techo 'pause' >\"$WHY_FILE\"\n+\texit 2\n+}\n+\n+\n+options_patch=\"\\\n+patch [options] <file>\n+--\n+3,3way Fall back to 3-way merge\n+k Pass to git-mailinfo (keep subject)\n+n Pass to git-mailinfo (no utf8)\n+$OPTIONS_GENERAL\n+ Options passed to git-apply:\n+R,reverse Reverse changes\n+context= Ensure context of ... lines\n+p= Remove ... leading slashes\n+unidiff-zero Bypass unidiff checks\n+exclude= Do not apply changes to given files\n+no-add Ignore additions of patch\n+whitespace= Set whitespace error behavior\n+inaccurate-eof Support inaccurate EOFs\n+u no-op (backward compatibility)\n+binary no-op (backward compatibility)\n+\"\n+\n+# Check the \"file\" instruction\n+check_patch () {\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-3|-k|-n|-u|--binary|-R|--reverse|--unidiff-zero|--no-add|--inaccurate-eof)\n+\t\t\t:\n+\t\t\t;;\n+\t\t-p|--whitespace|--exclude|--context)\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\tcheck_general_option \"$@\" ||\n+\t\t\t\ttodo_warn \"Unknown option $1\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\t\t\tbreak\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tif test -f \"$1\" -a -r \"$1\"\n+\tthen\n+\t\tgrep -e '^diff' \"$1\" >/dev/null ||\n+\t\t\ttodo_error \"File '$1' contains no patch.\"\n+\telse\n+\t\ttodo_error \"Cannot open file '$1'.\"\n+\tfi\n+\treturn 0\n+}\n+\n+# Realize the \"patch\" instruction\n+insn_patch () {\n+\tcomment_for_reflog patch\n+\n+\tapply_opts=\n+\tmailinfo_opts=\n+\tthreeway=\n+\n+\t# temporary files\n+\tinfofile=\"$SEQ_DIR/patch-info\"\n+\tmsgfile=\"$SEQ_DIR/patch-msg\"\n+\n+\twhile test \"$#\" -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-3)\n+\t\t\tthreeway=t\n+\t\t\t;;\n+\t\t-k|-n)\n+\t\t\tmailinfo_opts=\"$mailinfo_opts $1\"\n+\t\t\t;;\n+\t\t-u|--binary)\n+\t\t\t: Do nothing. It is there due to b/c only.\n+\t\t\t;;\n+\t\t-R|--reverse|--unidiff-zero|--no-add|--inaccurate-eof)\n+\t\t\tapply_opts=\"$apply_opts $1\"\n+\t\t\t;;\n+\t\t-p)\n+\t\t\tshift\n+\t\t\tapply_opts=\"$apply_opts -p$1\"\n+\t\t\t;;\n+\t\t--whitespace|--exclude)\n+\t\t\tapply_opts=\"$apply_opts $1=$2\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--context)\n+\t\t\tshift\n+\t\t\tapply_opts=\"$apply_opts -C$1\"\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t*)\n+\t\t\thandle_general_option \"$@\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tfilename=\"$1\"\n+\n+\tmark_action_done\n+\n+\tgit mailinfo $mailinfo_opts \"$msgfile\" \"$PATCH\" \\\n+\t\t<\"$filename\" >\"$infofile\" ||\n+\t\tdie_abort 'Could not read or parse mail'\n+\n+\tif test -z \"$AUTHOR\"\n+\tthen\n+\t\tsed -n -e '\n+\t\t\ts/^Author: \\(.*\\)$/GIT_AUTHOR_NAME=\"\\1\"/p;\n+\t\t\ts/^Email: \\(.*\\)$/GIT_AUTHOR_EMAIL=\"\\1\"/p;\n+\t\t\ts/^Date: \\(.*\\)$/GIT_AUTHOR_DATE=\"\\1\"/p\n+\t\t' <\"$infofile\" >>\"$AUTHOR_SCRIPT\"\n+\t\t# If sed's result is empty, we keep the original\n+\t\t# author script by appending.\n+\tfi\n+\n+\t# Ignore every mail that's not containing a patch\n+\ttest -s \"$PATCH\" || {\n+\t\twarn 'Does not contain patch!'\n+\t\treturn 0\n+\t}\n+\n+\tedit_msg=\n+\tif grep -e '^Subject:' \"$infofile\" >/dev/null\n+\tthen\n+\t\t# add subject to commit message\n+\t\tsed -n -e '/^Subject:/ s/Subject: //p' <\"$infofile\"\n+\t\techo\n+\t\techo\n+\t\tcat \"$msgfile\"\n+\telse\n+\t\tcat \"$msgfile\"\n+\t\tedit_msg=t\n+\tfi | git stripspace >\"$MSG\"\n+\trm -f \"$infofile\" \"$msgfile\"\n+\n+\tfirstline=$(sed -e '1q' <\"$MSG\")\n+\n+\tget_current_author\n+\n+\ttest -n \"$MESSAGE\" && printf '%s\\n' \"$MESSAGE\" >\"$MSG\"\n+\ttest -z \"$firstline\" && firstline=$(sed -e '1q' <\"$MSG\")\n+\n+\tdashdash_signoff\n+\n+\twith_author run_hook applypatch-msg \"$MSG\"\n+\tfailed=\n+\twith_author git apply $apply_opts --index \"$PATCH\" || failed=t\n+\n+\tif test -n \"$failed\" -a -n \"$threeway\" && (with_author fallback_3way)\n+\tthen\n+\t\t# Applying the patch to an earlier tree and merging the\n+\t\t# result may have produced the same tree as ours.\n+\t\tgit diff-index --quiet --cached HEAD -- && {\n+\t\t\techo 'No changes -- Patch already applied.'\n+\t\t\treturn 0\n+\t\t\t# XXX: do we want that?\n+\t\t}\n+\t\t# clear apply_status -- we have successfully merged.\n+\t\tfailed=\n+\tfi\n+\n+\tif test -n \"$failed\"\n+\tthen\n+\t\t# XXX: This is just a stupid hack:\n+\t\twith_author git apply $apply_opts --reject --index \"$PATCH\"\n+\t\tdie_to_continue 'Patch failed. See the .rej files.'\n+\t\t# XXX: We actually needed a git-apply flag that creates\n+\t\t# conflict markers and sets the DIFF_STATUS_UNMERGED flag.\n+\tfi\n+\n+\twith_author run_hook pre-applypatch\n+\n+\ttest -n \"$EDIT\" && edit_msg=t\n+\tif ! has_message \"$MSG\" || test -n \"$edit_msg\"\n+\tthen\n+\t\techo \"\n+# Please enter the commit message for the applied patch.\n+# (Comment lines starting with '#' will not be included)\" >>\"$MSG\"\n+\n+\t\tgit_editor \"$MSG\" ||\n+\t\t\tdie_with_patch 'Editor returned error.'\n+\t\thas_message \"$MSG\" ||\n+\t\t\tdie_with_patch 'No commit message given.'\n+\tfi\n+\n+\ttree=$(git write-tree) &&\n+\tparent=$(git rev-parse --verify HEAD) &&\n+\tcommit=$(git commit-tree \"$tree\" -p \"$parent\" <\"$MSG\") &&\n+\tgit update-ref -m \"$GIT_REFLOG_ACTION: $firstline\" HEAD \"$commit\" \"$parent\" ||\n+\t\tdie_to_continue 'Could not commit tree.'\n+\n+\ttest -x \"$GIT_DIR/hooks/post-applypatch\" &&\n+\t\twith_author \"$GIT_DIR/hooks/post-applypatch\"\n+\n+\treturn 0\n+}\n+\n+\n+options_pick=\"\\\n+pick [options] <commit>\n+--\n+R,reverse Revert introduced changes\n+mainline= Specify parent number to use for merge commits\n+$OPTIONS_GENERAL\n+\"\n+\n+# Check the \"pick\" instruction\n+check_pick () {\n+\trevert=\n+\tmainline=\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-R)\n+\t\t\trevert=\"$1\"\n+\t\t\t;;\n+\t\t--mainline)\n+\t\t\tshift\n+\t\t\tmainline=\"$1\"\n+\t\t\ttest \"$mainline\" -gt 0 || {\n+\t\t\t\ttodo_error '--mainline needs an integer beginning from 1.'\n+\t\t\t\tmainline=\n+\t\t\t}\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\tcheck_general_option \"$@\" ||\n+\t\t\t\ttodo_warn \"Unknown option $1\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\t\t\tbreak\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tif test -n \"$mainline\"\n+\tthen\n+\t\ttest -z \"$revert\" ||\n+\t\t\ttodo_error \"Cannot use $revert together with --mainline.\"\n+\n+\t\tparents=$(count_parents \"$1\")\n+\t\ttest \"$parents\" -lt \"$mainline\" &&\n+\t\t\ttodo_error \"Commit has only $parents (less than $mainline) parents.\"\n+\t\ttest \"$parents\" -eq 1 &&\n+\t\t\ttodo_warn 'Commit is not a merge at all.'\n+\tfi\n+\n+\tcommit_check \"$1\"\n+\n+\treturn 0\n+}\n+\n+# Realize the \"pick\" instruction\n+insn_pick () {\n+\top=cherry-pick\n+\tmainline=\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-R)\n+\t\t\top=revert\n+\t\t\t;;\n+\t\t--mainline)\n+\t\t\tmainline=\"$1 $2\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\thandle_general_option \"$@\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tsha1=$(git rev-parse --verify \"$1\")\n+\n+\tcomment_for_reflog pick\n+\n+\tmark_action_done\n+\n+\tedit_msg=\"$EDIT\"\n+\n+\t# Don't edit on pick, but later, if author or message given.\n+\ttest -n \"$AUTHOR\" -o -n \"$MESSAGE\" && edit_msg=\n+\n+\t# Be kind to users and ignore --mainline=1 on non-merge commits\n+\ttest -n \"$mainline\" -a 2 -gt $(count_parents \"$sha1\") && mainline=\n+\n+\tuse_output=\n+\ttest -n \"$edit_msg\" ||\n+\t\tuse_output=output\n+\n+\tpick_one \"$op\" $edit_msg $mainline $sha1 ||\n+\t\tdie_with_patch $sha1 \"Could not apply $sha1\"\n+\n+\ttest -n \"$EDIT\" ||\n+\t\tuse_output=output\n+\n+\tget_current_author\n+\tsignoff=\n+\ttest -n \"$SIGNOFF\" && signoff=-s\n+\tif test -n \"$AUTHOR\" -a -n \"$MESSAGE\"\n+\tthen\n+\t\t# this is just because we only want to do ONE amending commit\n+\t\t$use_output git commit --amend $EDIT $signoff --no-verify \\\n+\t\t\t--author \"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\" \\\n+\t\t\t--message=\"$MESSAGE\"\n+\telse\n+\t\t# correct author if AUTHOR is set\n+\t\ttest -n \"$AUTHOR\" &&\n+\t\t\t$use_output git commit --amend $EDIT --no-verify -C HEAD \\\n+\t\t\t\t--author \"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\"\n+\t\t# XXX: a git-cherry-pick --author could be nicer here\n+\t\t# correct commit message if MESSAGE is set\n+\t\ttest -n \"$MESSAGE\" &&\n+\t\t\t$use_output git commit --amend $EDIT $signoff --no-verify \\\n+\t\t\t\t-C HEAD --message=\"$MESSAGE\"\n+\tfi\n+\n+\treturn 0\n+}\n+\n+options_edit=\"\\\n+edit <commit>\n+--\n+\"\n+\n+# Check the \"edit\" instruction\n+check_edit () {\n+\tshift\n+\ttest -z \"$BATCHMODE\" ||\n+\t\ttodo_error '\"edit\" instruction and --batch do not make sense together.'\n+\ttest $# -eq 1 ||\n+\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\treturn 0\n+}\n+\n+# Realize the \"edit\" instruction\n+insn_edit () {\n+\tshift\n+\tinsn_pick \"$1\"\n+\n+\t# work around mark_action_done in insn_pause\n+\techo '# pausing' >\"$TODO.new\"\n+\tcat \"$TODO\" >>\"$TODO.new\"\n+\tmv -f \"$TODO.new\" \"$TODO\"\n+\tinsn_pause\n+}\n+\n+\n+options_squash=\"\\\n+squash <commit>\n+squash [options] --from <mark>\n+--\n+from Squash all commits from <mark>\n+collect-signoffs Collect Signed-off-by: lines\n+include-merges Do not fail on merge commits\n+$OPTIONS_GENERAL\n+\"\n+\n+# Check the \"squash\" instruction\n+check_squash () {\n+\tfrom=\n+\tcollect=\n+\tmerges=\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t--from)\n+\t\t\tfrom=t\n+\t\t\t;;\n+\t\t--collect-signoffs)\n+\t\t\tcollect=t\n+\t\t\ttodo_warn 'Not yet implemented.'\n+\t\t\t;;\n+\t\t--include-merges)\n+\t\t\tmerges=t\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t*)\n+\t\t\tcheck_general_option \"$@\" ||\n+\t\t\t\ttodo_error \"Unknown option $1\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\t# in --from mode?\n+\tif test -n \"$from\"\n+\tthen\n+\t\ttest -z \"$merges\" &&\n+\t\t\tcat \"$DONE\" \"$TODO\" |\n+\t\t\tsed -n -e '/^[ \\t]*mark[ \\t]*:\\{0,1\\}'\"${1#:}\"'\\($\\|[^0-9]\\)/,'\"$line\"'p' |\n+\t\t\tgrep '^[ \\t]*merge' >/dev/null &&\n+\t\t\ttodo_error \"$1..HEAD contains a merge commit. You may try --include-merges.\"\n+\n+\t\targ_is_mark_check \"$1\"\n+\telse\n+\t\ttest -n \"$merges\" &&\n+\t\t\ttodo_error '--include-merges only makes sense with --from <mark>.'\n+\t\ttest -n \"$collect\" &&\n+\t\t\ttodo_error '--collect-signoffs only makes sense with --from <mark>.'\n+\n+\t\tcommit_check \"$1\"\n+\tfi\n+\n+\treturn 0\n+}\n+\n+# Realize the \"squash\" instruction\n+insn_squash () {\n+\tsquash_msg=\"$MSG-squash\"\n+\tfrom=\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t--from)\n+\t\t\tfrom=t\n+\t\t\t;;\n+\t\t--collect-signoffs)\n+\t\t\twarn '--collect-signoffs is not implemented.'\n+\t\t\t# XXX\n+\t\t\t;;\n+\t\t--include-merges)\n+\t\t\t: # This has to be done during check_squash\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t*)\n+\t\t\thandle_general_option \"$@\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tif test -n \"$from\"\n+\tthen\n+\t\tsha1=$(mark_to_commit \":${1#:}\")\n+\telse\n+\t\tsha1=$(git rev-parse --verify \"$1\")\n+\tfi\n+\n+\tcomment_for_reflog squash\n+\n+\t# Hm, somehow I don't think --skip on a conflicting squash\n+\t# may be useful, but if someone wants to do it, it should\n+\t# do the obvious: skip what squash would do.\n+\techo \"$(git rev-parse HEAD)\" >\"$SEQ_DIR/skiphead\"\n+\n+\tmark_action_done\n+\n+\tif test -n \"$MESSAGE\"\n+\tthen\n+\t\tprintf '%s\\n' \"$MESSAGE\" >\"$MSG\"\n+\telse\n+\t\tif test -n \"$from\"\n+\t\tthen\n+\t\t\tmake_squash_message_multiple \"$sha1\"\n+\t\telse\n+\t\t\tmake_squash_message \"$sha1\" >\"$MSG\"\n+\t\tfi\n+\tfi\n+\n+\tcase \"$(peek_next_command)\" in\n+\tsquash)\n+\t\tedit_commit=\n+\t\tuse_output=output\n+\t\tcp \"$MSG\" \"$squash_msg\"\n+\t\t;;\n+\t*)\n+\t\tedit_commit=-e\n+\t\tuse_output=\n+\t\trm -f \"$squash_msg\" || exit\n+\t\t;;\n+\tesac\n+\n+\ttest -n \"$MESSAGE\" && edit_commit=\n+\ttest -n \"$EDIT\" && edit_commit=-e\n+\n+\t# is --author (or equivalent) set?\n+\tif test -n \"$AUTHOR\"\n+\tthen\n+\t\t# evaluate author script\n+\t\tget_current_author\n+\telse\n+\t\t# if --author is not given, we get the authorship\n+\t\t# information from the commit before.\n+\t\teval \"$(get_author_ident_from_commit HEAD)\"\n+\t\t# but we do not write an author script\n+\tfi\n+\n+\t# --from or not\n+\tfailed=\n+\tif test -n \"$from\"\n+\tthen\n+\t\toutput git reset --soft \"$sha1\"\n+\telse\n+\t\toutput git reset --soft HEAD^\n+\n+\t\tpick_one cherry-pick -n \"$sha1\" || failed=t\n+\tfi\n+\n+\tdashdash_signoff\n+\n+\tif test -z \"$failed\"\n+\tthen\n+\t\t# This is like --amend, but with a different message\n+\t\twith_author $use_output git commit --no-verify \\\n+\t\t\t-F \"$MSG\" $edit_commit || failed=t\n+\telse\n+\t\tcp \"$MSG\" \"$GIT_DIR/MERGE_MSG\"\n+\t\twarn\n+\t\twarn \"Could not apply $sha1...\"\n+\t\tdie_with_patch $sha1 \"\"\n+\tfi\n+\n+\treturn 0\n+}\n+\n+\n+options_mark=\"\\\n+mark <mark>\n+--\n+\"\n+\n+# Check the \"mark\" instruction\n+check_mark () {\n+\tshift\n+\ttest $# -eq 1 ||\n+\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\tmy_mark=$(expr \"x${1#:}\" : 'x0*\\([0-9][0-9]*\\)$')\n+\ttest -n \"$my_mark\" ||\n+\t\ttodo_error \"Mark $1 not an integer.\"\n+\texpr \"x$available_marks \" : \" $my_mark \" >/dev/null &&\n+\t\ttodo_error \"Mark :$my_mark already defined. Choose another integer.\"\n+\tavailable_marks=\"$available_marks $my_mark\"\n+\n+\treturn 0\n+}\n+\n+# Realize the \"mark\" instruction\n+insn_mark () {\n+\tshift\n+\tgiven=\"$1\"\n+\n+\tmark_action_done\n+\n+\tmark=$(mark_to_ref \":${given#:}\")\n+\tgit update-ref \"$mark\" HEAD\n+\treturn 0\n+}\n+\n+\n+options_merge=\"\\\n+merge [options] <commit-ish> ...\n+--\n+standard Generate default commit message\n+s,strategy= Use merge strategy ...\n+$OPTIONS_GENERAL\n+\"\n+\n+# Check the \"merge\" instruction\n+check_merge () {\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t--standard)\n+\t\t\tmsg_opt=\"t$msg_opt\"\n+\t\t\t;;\n+\t\t-s)\n+\t\t\tshift\n+\t\t\tstrategy_check \"$1\"\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\tcheck_general_option \"$@\" ||\n+\t\t\t\ttodo_error \"Unknown option $1\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\ttest $# -gt 0 ||\n+\t\ttodo_error 'What are my parents? Need new parents!'\n+\n+\twhile test $# -gt 0\n+\tdo\n+\t\targ_is_mark_or_commit_check \"$1\"\n+\t\tshift\n+\tdone\n+\treturn 0\n+}\n+\n+# Realize the \"merge\" instruction\n+insn_merge () {\n+\tcomment_for_reflog merge\n+\n+\tstandard=\n+\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t--standard)\n+\t\t\tstandard=t\n+\t\t\t;;\n+\t\t-s)\n+\t\t\tshift\n+\t\t\tstrategy=\"-s $1\"\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\thandle_general_option \"$@\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tnew_parents=\n+\tfor p in \"$@\"\n+\tdo\n+\t\tnew_parents=\"$new_parents $(mark_to_ref $p)\"\n+\tdone\n+\tnew_parents=\"${new_parents# }\"\n+\n+\tget_current_author\n+\n+\tif test -n \"$standard\"\n+\tthen\n+\t\tfor cur_parent in $new_parents\n+\t\tdo\n+\t\t\tprintf '%s\\t\\t%s' \\\n+\t\t\t\t\"$(git rev-parse \"$cur_parent\")\" \"$cur_parent\"\n+\t\tdone | git fmt-merge-msg >\"$MSG\"\n+\tfi\n+\n+\ttest -n \"$MESSAGE\" &&\n+\t\tprintf '%s\\n' \"$MESSAGE\" >\"$MSG\"\n+\n+\tdashdash_signoff\n+\tif ! has_message \"$MSG\" || test -n \"$EDIT\"\n+\tthen\n+\t\techo \"\n+# Please enter the merge commit message.\n+# (Comment lines starting with '#' will not be included)\" >>\"$MSG\"\n+\n+\t\tgit_editor \"$MSG\" ||\n+\t\t\tdie_with_patch 'Editor returned error.'\n+\t\thas_message \"$MSG\" ||\n+\t\t\tdie_with_patch 'No commit message given.'\n+\tfi\n+\n+\tmark_action_done\n+\tif ! with_author output git merge $strategy -m junk $new_parents\n+\tthen\n+\t\tgit rerere\n+\t\tcat \"$MSG\" >\"$GIT_DIR/MERGE_MSG\"\n+\t\tdie_to_continue 'Error merging'\n+\tfi\n+\twith_author output git commit --amend -F \"$MSG\" --no-verify\n+\treturn 0\n+}\n+\n+\n+options_reset=\"\\\n+reset <commit-ish>\n+--\n+\"\n+\n+# Check the \"reset\" instruction\n+check_reset () {\n+\tshift\n+\ttest $# -eq 1 ||\n+\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\targ_is_mark_or_commit_check \"$1\"\n+\n+\treturn 0\n+}\n+\n+# Realize the \"reset\" instruction\n+insn_reset () {\n+\tshift\n+\tcomment_for_reflog reset\n+\n+\tmark_action_done\n+\toutput git reset --hard \"$(mark_to_commit \"$1\")\"\n+}\n+\n+\n+options_ref=\"\\\n+ref <ref>\n+--\n+\"\n+\n+# Check the \"ref\" instruction\n+check_ref () {\n+\tshift\n+\ttest $# -eq 1 ||\n+\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\treturn 0\n+}\n+\n+# Realize the \"ref\" instruction\n+insn_ref () {\n+\tshift\n+\tcomment_for_reflog ref\n+\n+\tmark_action_done\n+\toutput git update-ref \"$1\" HEAD\n+}\n+\n+\n+### Instruction main loop\n+\n+# Run check_* or insn_* with massaged options\n+# Usage: run_insn (check|do) <insn> <insn options>\n+run_insn () {\n+\tc_or_i=\"$1\"\n+\tinsn=\"$2\"\n+\tshift\n+\tshift\n+\teval \"option_spec=\\\"\\$options_$insn\\\"\"\n+\teval \"$(printf \"%s\" \"$option_spec\" |\n+\t\tgit rev-parse --parseopt -- \"$@\" ||\n+\t\techo return)\"\n+\tcase \"$c_or_i\" in\n+\tcheck)\n+\t\tcheck_$insn \"$@\"\n+\t\t;;\n+\tdo)\n+\t\tinsn_$insn \"$@\"\n+\t\t;;\n+\tesac\n+}\n+\n+# Execute the first line of the current TODO file\n+execute_next () {\n+\trm -f \"$MSG\"\n+\techo 'HEAD' >\"$SEQ_DIR/skiphead\"\n+\tread command rol <\"$TODO\"\n+\tcase \"$command\" in\n+\t'#'*|'')\n+\t\tmark_action_done\n+\t\t;;\n+\t*)\n+\t\ttest \"$VERBOSE\" -gt 1 &&\n+\t\t\techo \"Next line: $command $rol\"\n+\n+\t\t# reset general options\n+\t\tclean_author_script\n+\t\tgeneral_shift=1\n+\t\tAUTHOR=\n+\t\tEDIT=\n+\t\tMESSAGE=\n+\t\tSIGNOFF=\n+\t\t# XXX: eval is evil!\n+\t\teval \"run_insn do $command $rol\" ||\n+\t\t\tdie_to_continue 'An unexpected error occured.'\n+\t\t;;\n+\tesac\n+}\n+\n+# Execute the rest of the TODO file and finish\n+execute_rest () {\n+\twhile has_action \"$TODO\"\n+\tdo\n+\t\texecute_next\n+\tdone\n+\n+\tcomment_for_reflog finish\n+\tif test -n \"$ONTO\"\n+\tthen\n+\t\tgit update-ref -m \"$GIT_REFLOG_ACTION: $ONTO\" \"$ONTO\" HEAD &&\n+\t\tgit symbolic-ref HEAD \"$ONTO\"\n+\tfi &&\n+\tquit\n+}\n+\n+\n+# Main loop to check instructions\n+todo_check () {\n+\ttodo=\"$TODO\"\n+\ttest -n \"$1\" && todo=\"$1\"\n+\n+\tavailable_marks=' '\n+\tfor cur_mark in $(git for-each-ref --format='%(refname)' \"$MARK_PREFIX\")\n+\tdo\n+\t\tavailable_marks=\"$available_marks ${cur_mark##*/}\"\n+\tdone\n+\n+\tretval=0\n+\tline=1\n+\twhile read command rol\n+\tdo\n+\t\tcase \"$command\" in\n+\t\t'#'*|'')\n+\t\t\t;;\n+\t\t*)\n+\t\t\teval 'test -n \"$options_'\"$command\"'\"' || {\n+\t\t\t\tretval=1\n+\t\t\t\ttodo_error \"Unknown $command instruction\"\n+\t\t\t\tcontinue\n+\t\t\t}\n+\n+\t\t\tgeneral_shift=1\n+\t\t\tmsg_opt=\n+\t\t\tauthor_opt=\n+\t\t\teval \"run_insn check $command $rol\" ||\n+\t\t\t\ttodo_error \"Unknown option used\"\n+\t\t\texpr \"$msg_opt\" : 'ttt*' >/dev/null &&\n+\t\t\t\ttodo_error 'You can only provide one commit message option.'\n+\t\t\texpr \"$author_opt\" : 'ttt*' >/dev/null &&\n+\t\t\t\ttodo_error 'You can only provide one author option.'\n+\t\t\t;;\n+\t\tesac\n+\t\tline=$(expr \"$line\" + 1)\n+\tdone <\"$todo\"\n+\treturn $retval\n+}\n+\n+prepare_editable_todo () {\n+\techo '# ALREADY DONE:'\n+\tsed -e 's/^/#  /' <\"$DONE\"\n+\techo '# '\n+\techo \"$markline\"\n+\tcat \"$TODO\"\n+}\n+\n+get_saved_options () {\n+\tVERBOSE=$(cat \"$SEQ_DIR/verbose\")\n+\tONTO=$(cat \"$SEQ_DIR/onto\")\n+\tWHY=$(cat \"$WHY_FILE\" 2>/dev/null)\n+\treturn 0\n+}\n+\n+# Realize sequencer invocation\n+do_startup () {\n+\ttest -d \"$SEQ_DIR\" &&\n+\t\tdie 'sequencer already started'\n+\n+\trequire_clean_work_tree\n+\n+\tHEAD=$(git rev-parse --verify HEAD) ||\n+\t\tdie 'No HEAD?'\n+\n+\tmkdir \"$SEQ_DIR\" ||\n+\t\tdie \"Could not create temporary $SEQ_DIR\"\n+\n+\t# save options\n+\techo \"$VERBOSE\" >\"$SEQ_DIR/verbose\"\n+\ttest -n \"$CALLERSTRING\" &&\n+\t\tgenerate_caller_script \"$CALLERSTRING\"\n+\t# generate empty DONE and \"onto\" file\n+\t: >\"$DONE\"\n+\t: >\"$SEQ_DIR/onto\"\n+\n+\tif test -n \"$BATCHMODE\"\n+\tthen\n+\t\tGIT_CHERRY_PICK_HELP='  Aborting (batch mode)'\n+\t\texport GIT_CHERRY_PICK_HELP\n+\telse\n+\t\tassure_caller\n+\tfi\n+\n+\tcomment_for_reflog start\n+\n+\t# save old head before checking out the given <branch>\n+\tgit symbolic-ref HEAD >\"$SEQ_DIR/head-name\" 2>/dev/null ||\n+\t\techo 'detached HEAD' >\"$SEQ_DIR/head-name\"\n+\techo $HEAD >\"$SEQ_DIR/head\"\n+\t# do it here so that die_abort can work ;)\n+\n+\tif test -n \"$ONTO\"\n+\tthen\n+\t\t# if ONTO is a branch name, then keep it, otherwise\n+\t\t# we don't care anymore and erase ONTO.\n+\t\tif git-show-ref --quiet --verify -- \"refs/heads/${ONTO##*/}\"\n+\t\tthen\n+\t\t\tONTO=\"refs/heads/${ONTO##*/}\"\n+\t\t\techo \"$ONTO\" >\"$SEQ_DIR/onto\"\n+\t\t\toutput git checkout \"$(git rev-parse \"$ONTO\")\" ||\n+\t\t\t\tdie_abort \"Could not checkout branch $ONTO\"\n+\t\telse\n+\t\t\toutput git checkout \"$ONTO\" ||\n+\t\t\t\tdie_abort \"Could not checkout commit $ONTO\"\n+\t\t\tONTO=\n+\t\tfi\n+\tfi\n+\n+\t(git var GIT_AUTHOR_IDENT || git var COMMITTER_IDENT) |\n+\t\tmake_author_script_from_string >\"$ORIG_AUTHOR_SCRIPT\"\n+\n+\t# read from file or from stdin?\n+\tif test -z \"$1\"\n+\tthen\n+\t\t: >\"$TODO\" ||\n+\t\t\tdie_abort \"Could not generate TODO file $TODO\"\n+\t\twhile read line\n+\t\tdo\n+\t\t\tprintf '%s\\n' \"$line\" >>\"$TODO\" ||\n+\t\t\t\tdie_abort \"Could not append to TODO file $TODO\"\n+\t\tdone\n+\telse\n+\t\tcp \"$1\" \"$TODO\" ||\n+\t\t\tdie_abort \"Could not find TODO file $1.\"\n+\tfi\n+\n+\thas_action \"$TODO\" || die_abort 'Nothing to do'\n+\ttodo_check || WHY=todo die_to_continue \"TODO file contains errors.\n+Fix with git sequencer --edit or abort with $(print_caller --abort).\"\n+\n+\texecute_rest\n+\texit\n+}\n+\n+# Realize --continue.\n+do_continue () {\n+\ttest -d \"$SEQ_DIR\" || die 'No sequencer running'\n+\ttest_caller 'continue'\n+\n+\ttodo_check || WHY=todo die_to_continue \"TODO file contains errors.\n+Fix with git sequencer --edit or abort with $(print_caller --abort).\"\n+\n+\tcomment_for_reflog continue\n+\n+\t# Sanity check\n+\tgit rev-parse --verify HEAD >/dev/null ||\n+\t\tdie_to_continue 'Cannot read HEAD'\n+\tgit update-index --ignore-submodules --refresh &&\n+\t\tgit diff-files --quiet --ignore-submodules ||\n+\t\tdie_to_continue 'Working tree is dirty. (Use git add or git stash first?)'\n+\n+\tget_saved_options\n+\n+\t# do we have anything to commit? (staged changes)\n+\tif ! git diff-index --cached --quiet --ignore-submodules HEAD --\n+\tthen\n+\t\t. \"$AUTHOR_SCRIPT\" ||\n+\t\t\tdie_to_continue 'Error evaluating author script. Must not happen!'\n+\n+\t\t# After \"pause\", we should amend (merge-safe!).\n+\t\t# On conflict, we do not have a commit to amend, so we\n+\t\t# should just commit.\n+\t\tcase \"$WHY\" in\n+\t\tpause)\n+\t\t\twith_author git commit --amend --no-verify -F \"$MSG\" -e ||\n+\t\t\t\tdie_to_continue 'Could not commit staged changes.'\n+\t\t\t;;\n+\t\tconflict)\n+\t\t\twith_author git commit --no-verify -F \"$MSG\" -e ||\n+\t\t\t\tdie_to_continue 'Could not commit staged changes.'\n+\t\t\techo '# resolved CONFLICTS of the last instruction' >>\"$DONE\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\tdie_to_continue 'There are staged changes. Do not know what to do with them.'\n+\t\tesac\n+\tfi\n+\n+\trequire_clean_work_tree\n+\trm -f \"$WHY_FILE\"\n+\texecute_rest\n+\texit\n+}\n+\n+# Realize --abort.\n+do_abort () {\n+\ttest -d \"$SEQ_DIR\" || die 'No sequencer running'\n+\ttest_caller 'abort'\n+\n+\tcomment_for_reflog abort\n+\trestore\n+\tquit\n+}\n+\n+# Realize --skip.\n+do_skip () {\n+\ttest -d \"$SEQ_DIR\" || die 'No sequencer running'\n+\ttest_caller 'skip'\n+\n+\ttodo_check || WHY=todo die_to_continue \"TODO file contains errors.\n+Fix with git sequencer --edit or abort with $(print_caller --abort).\"\n+\tget_saved_options\n+\n+\tcomment_for_reflog skip\n+\tgit rerere clear\n+\n+\toutput git reset --hard \"$(cat \"$SEQ_DIR/skiphead\")\" &&\n+\trm -f \"$WHY_FILE\" &&\n+\techo '# SKIPPED the last instruction' >>\"$DONE\" &&\n+\t\texecute_rest\n+\texit\n+}\n+\n+# Realize --edit.\n+do_edit () {\n+\ttest -d \"$SEQ_DIR\" || die 'No sequencer running'\n+\n+\tmarkline='### BEGIN EDITING BELOW THIS LINE ###'\n+\tprepare_editable_todo >\"$TODO.new\"\n+\n+\t# XXX: does not make sense\n+\t#      when input does not come from a terminal\n+\tgit_editor \"$TODO.new\" ||\n+\t\tdie 'Editor returned an error.'\n+\n+\tif test -t 0 -a -t 1\n+\tthen\n+\t\techo\n+\t\t# interactive:\n+\t\tuntil has_action \"$TODO.new\" && todo_check \"$TODO.new\"\n+\t\tdo\n+\t\t\thas_action \"$TODO.new\" || echo 'TODO file empty.'\n+\t\t\tprintf 'What to do with the file? [c]orrect/[e]dit again/[r]ewind/[s]ave/[?] '\n+\t\t\tread reply\n+\t\t\tcase \"$reply\" in\n+\t\t\t[cC]*)\n+\t\t\t\tgit_editor \"$TODO.new\"\n+\t\t\t\t;;\n+\t\t\t[eE]*)\n+\t\t\t\tprepare_editable_todo >\"$TODO.new\"\n+\t\t\t\tgit_editor \"$TODO.new\"\n+\t\t\t\t;;\n+\t\t\t[rRxXqQ]*)\n+\t\t\t\trm -f \"$TODO.new\"\n+\t\t\t\texit 0\n+\t\t\t\t;;\n+\t\t\t[sS]*)\n+\t\t\t\ttest \"$WHY\" != 'pause' ||\n+\t\t\t\t\techo 'todo' >\"$WHY_FILE\"\n+\t\t\t\tbreak\n+\t\t\t\t;;\n+\t\t\t[?hH]*)\n+\t\t\t\tcat <<EOF\n+\n+Help:\n+s - save TODO file and exit\n+c - respawn editor to correct TODO file\n+e - drop changes and respawn editor on original TODO file\n+r - drop changes and exit as if nothing happened\n+? - print this help\n+EOF\n+\t\t\t\t;;\n+\t\t\tesac\n+\t\t\techo\n+\t\tdone\n+\telse\n+\t\t# defaults:\n+\t\thas_action \"$TODO.new\" || quit \"Nothing to do\"\n+\t\ttodo_check || die 'TODO file contains errors. Aborting.'\n+\tfi\n+\tcat \"$TODO\" >\"$TODO.old\"\n+\tif grep \"^$markline\" \"$TODO.new\" >/dev/null\n+\tthen\n+\t\tsed -e \"1,/^$markline/d\" <\"$TODO.new\" >\"$TODO\"\n+\telse\n+\t\tcat \"$TODO.new\" >\"$TODO\"\n+\tfi\n+\trm -f \"$TODO.new\"\n+\techo\n+\techo 'TODO file contains:'\n+\techo\n+\tcat \"$TODO\"\n+\texit 0\n+}\n+\n+# Realize --status.\n+do_status () {\n+\ttest -d \"$SEQ_DIR\" || die 'No sequencer running.'\n+\tget_saved_options\n+\n+\tif has_action \"$DONE\"\n+\tthen\n+\t\techo 'Already done:'\n+\t\tsed -e 's/^/  /' <\"$DONE\"\n+\t\techo\n+\tfi\n+\tcase \"$WHY\" in\n+\tpause)\n+\t\techo 'Intentionally paused.'\n+\t\t;;\n+\tconflict)\n+\t\techo 'Interrupted by conflict at'\n+\t\tsed -n -e 's/^/  /;$p' <\"$DONE\"\n+\t\t;;\n+\ttodo)\n+\t\techo 'Interrupted because of errors in the TODO file.'\n+\t\t;;\n+\t*)\n+\t\techo 'Current state is broken.'\n+\tesac\n+\ttest \"$VERBOSE\" -gt 1 && echo 'Running verbosely.'\n+\ttest \"$VERBOSE\" -lt 1 && echo 'Running quietly.'\n+\ttest -n \"$ONTO\" &&\n+\t\techo \"Sequencing on branch ${ONTO##*/}.\"\n+\tif has_action \"$TODO\"\n+\tthen\n+\t\techo\n+\n+\t\techo 'Still to do:'\n+\t\tsed -e 's/^/  /' <\"$TODO\"\n+\tfi\n+\tif test \"$WHY\" = todo\n+\tthen\n+\t\techo\n+\t\techo 'But there are errors. To edit, run:'\n+\t\techo '    git sequencer --edit'\n+\telse\n+\t\techo\n+\t\techo 'To abort & restore, invoke:'\n+\t\techo \"    $(print_caller --abort)\"\n+\t\techo 'To continue, invoke:'\n+\t\techo \"    $(print_caller --continue)\"\n+\t\ttest \"$WHY\" = 'pause' || {\n+\t\t\techo 'To skip the current instruction, invoke:'\n+\t\t\techo \"    $(print_caller --skip)\"\n+\t\t}\n+\tfi\n+\texit 0\n+}\n+\n+is_standalone () {\n+\ttest $# -eq 2 &&\n+\ttest \"$2\" = '--' &&\n+\ttest -z \"$BATCHMODE\" &&\n+\ttest -z \"$onto\" &&\n+\ttest \"$VERBOSE\" -eq 1\n+}\n+\n+\n+### Option handling and startup\n+\n+onto=\n+BATCHMODE=\n+CALLERSTRING=\n+VERBOSE=1\n+CALLER=\n+CALLER_ABRT=\n+CALLER_CONT=\n+CALLER_SKIP=\n+while test $# -gt 0\n+do\n+\tcase \"$1\" in\n+\t--continue)\n+\t\tis_standalone \"$@\" || usage\n+\t\tassure_caller\n+\t\tdo_continue\n+\t\t;;\n+\t--abort)\n+\t\tis_standalone \"$@\" || usage\n+\t\tassure_caller\n+\t\tdo_abort\n+\t\t;;\n+\t--skip)\n+\t\tis_standalone \"$@\" || usage\n+\t\tassure_caller\n+\t\tdo_skip\n+\t\t;;\n+\t--status)\n+\t\tis_standalone \"$@\" || usage\n+\t\tassure_caller\n+\t\tdo_status\n+\t\t;;\n+\t--edit)\n+\t\tis_standalone \"$@\" || usage\n+\t\tdo_edit\n+\t\t;;\n+\t--caller)\n+\t\t###############################################################\n+\t\t# This feature is for user scripts only. (Hence undocumented.)\n+\t\t# User scripts should pass an argument like:\n+\t\t# --caller=\"git foo|abrt|go|next\"\n+\t\t# on every git sequencer call. (It is only ignored on\n+\t\t# --edit and --status.)\n+\t\t# So git sequencer knows that\n+\t\t# \"git foo abrt\" will abort,\n+\t\t# \"git foo go\" will continue and\n+\t\t# \"git foo next\" will skip the sequencing process.\n+\t\t# This is useful if your user script does some extra\n+\t\t# preparations or cleanup before/after calling\n+\t\t#   git sequencer --caller=\"...\" --abort|--continue|--skip\n+\t\t#\n+\t\t# Running git-sequencer without the same --caller string\n+\t\t# fails then, until the sequencing process has finished or\n+\t\t# aborted.\n+\t\t#\n+\t\t# Btw, --caller=\"my_tiny_script.sh|-a||\" will be\n+\t\t# interpreted, that users must invoke \"my_tiny_script.sh -a\"\n+\t\t# to abort, but can invoke \"git sequencer --continue\" and\n+\t\t# \"git sequencer --skip\" to continue or skip.\n+\t\t# And it is also possible to provide three different scripts\n+\t\t# by --caller=\"|script 1|tool 2|util 3\".\n+\t\t#\n+\t\t# If your user script does not need any special\n+\t\t# abort/continue/skip behavior, then just do NOT pass\n+\t\t# the --caller option.\n+\t\t###############################################################\n+\t\tshift\n+\t\texpr \"x$1\" : 'x.*|.*|.*|.*$' >/dev/null ||\n+\t\t\tdie 'Wrong --caller format.'\n+\t\tCALLERSTRING=\"$1\"\n+\t\t;;\n+\t-B)\n+\t\tBATCHMODE=t\n+\t\t# XXX: we still have abort on editor invokations\n+\t\t;;\n+\t--onto)\n+\t\tshift\n+\t\tONTO=\"$1\"\n+\t\ttest $(git cat-file -t \"$ONTO\") = 'commit' ||\n+\t\t\tdie \"$ONTO is no commit or branch.\"\n+\t\t;;\n+\t-q)\n+\t\tVERBOSE=0\n+\t\t# XXX: If there were no editors,\n+\t\t# we could just do exec >/dev/null\n+\t\t;;\n+\t-v)\n+\t\tVERBOSE=2\n+\t\t# or increment it if we have several verbosity steps\n+\t\t;;\n+\t--)\n+\t\tshift\n+\t\tbreak\n+\t\t;;\n+\t*)\n+\t\tdie \"$1 currently not implemented.\"\n+\t\t;;\n+\tesac\n+\tshift\n+done\n+test $# -gt 1 && usage\n+\n+do_startup \"$1\"\n-- \n1.5.6.1.130.ga8860.dirty\n"},{"id":"81824","messageId":"1214879914-17866-3-git-send-email-s-beyer@gmx.net","threadId":"14239","inReplyTo":"1214879914-17866-2-git-send-email-s-beyer@gmx.net","subject":"[RFC/PATCH 2/4] Add git-sequencer prototype documentation","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-01T02:38:32Z","receivedAt":"2008-07-01T02:38:32Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Mentored-by: Christian Couder <chriscool@tuxfamily.org>\nMentored-by: Daniel Barkalow <barkalow@iabervon.org>\nSigned-off-by: Stephan Beyer <s-beyer@gmx.net>\n---\n Documentation/git-sequencer.txt |  348 +++++++++++++++++++++++++++++++++++++++\n 1 files changed, 348 insertions(+), 0 deletions(-)\n create mode 100644 Documentation/git-sequencer.txt\n\ndiff --git a/Documentation/git-sequencer.txt b/Documentation/git-sequencer.txt\nnew file mode 100644\nindex 0000000..e0c6410\n--- /dev/null\n+++ b/Documentation/git-sequencer.txt\n@@ -0,0 +1,348 @@\n+git-sequencer(1)\n+================\n+\n+NAME\n+----\n+git-sequencer - Execute a sequence of git instructions\n+\n+SYNOPSIS\n+--------\n+[verse]\n+'git-sequencer' [--batch] [--onto=<base>] [--verbose|--quiet] [<file>]\n+'git-sequencer' --continue | --skip | --abort | --edit | --status\n+\n+\n+DESCRIPTION\n+-----------\n+Executes a sequence of git instructions to HEAD or `<base>`.\n+The sequence is given by `<file>` or standard input.\n+Also see 'TODO FILE FORMAT' below.\n+\n+Before doing anything, the TODO file is checked for correct syntax\n+and sanity.\n+\n+In case of a conflict or request in the TODO file, git-sequencer will\n+pause. On conflict you can use git-diff to locate the markers (`<<<<<<<`)\n+and make edits to resolve the conflict.\n+\n+For each file you edit, you need to tell git the changes by doing\n+\n+    git add <file>\n+\n+After resolving the conflict manually and updating the index with the\n+desired resolution, you can continue the sequencing process with\n+\n+    git sequencer --continue\n+\n+Alternatively, you can undo the git-sequencer progress with\n+\n+    git sequencer --abort\n+\n+or skip the current instruction with\n+\n+    git sequencer --skip\n+\n+or correct the TODO file with\n+\n+    git sequencer --edit\n+\n+During pauses or when finished with the sequencing task, the current\n+HEAD will always be the result of the last processed instruction.\n+\n+\n+OPTIONS\n+-------\n+<file>::\n+\tFilename of the TODO file.  If omitted, standard input is used.\n+\tSee 'TODO FILE FORMAT' below.\n+\n+-B::\n+--batch::\n+\tRun in batch mode. If unexpected user intervention is needed\n+\t(e.g. a conflict or the need to run an editor), git-sequencer fails.\n++\n+Note that the sanity check fails, if you use this option\n+and an instruction like `edit` or `pause`.\n+\n+--onto=<base>::\n+\tCheckout given commit or branch before sequencing.\n+\tIf you provide a branch, sequencer will make the provided\n+\tchanges on the branch, i.e. the branch will be changed.\n+\n+--continue::\n+\tRestart the sequencing process after having resolved a merge conflict.\n+\n+--abort::\n+\tRestore the original branch and abort the sequence operation.\n+\n+--skip::\n+\tRestart the sequencing process by skipping the current instruction.\n+\n+--status::\n+\tShow the current status of git-sequencer and what\n+\toperations can be done to change that status.\n+\n+--edit::\n+\tInvoke editor to edit the undone rest of the TODO file.\n++\n+The file is syntax- and sanity-checked afterwards, so that you can\n+safely run `git sequencer --skip` or `--continue` after editing.\n+If you nonetheless noticed that you made a mistake, you can\n+overwrite `.git/sequencer/todo` with `.git/sequencer/todo.old` and\n+rerun `git sequencer --edit`.\n++\n+If the check fails you are prompted if you want to correct your\n+changes, edit again, cancel editing or really want to save.\n+\n+-q::\n+--quiet::\n+\tSuppress output.\n+\t(Not yet implemented.)\n+\n+-v::\n+--verbose::\n+\tBe more verbose.\n+\n+\n+NOTES\n+-----\n+\n+When sequencing, it is possible, that you are changing the history of\n+a branch in a way that can cause problems for anyone who already has\n+a copy of the branch in their repository and tries to pull updates from\n+you.  You should understand the implications of using git-sequencer on\n+a repository that you share.\n+\n+git-sequencer will usually be called by another git porcelain, like\n+linkgit:git-am[1] or linkgit:git-rebase[1].\n+\n+\n+TODO FILE FORMAT\n+----------------\n+\n+The TODO file contains basically one instruction per line.\n+\n+Blank lines will be ignored.\n+All characters after a `#` character will be ignored until the end of a line.\n+\n+The following instructions can be used:\n+\n+\n+edit <commit>::\n+\tPicks a commit and pauses the sequencer process to let you\n+\tmake changes.\n++\n+This is a short form for `pick <commit> and `pause` on separate lines.\n+\n+\n+mark <mark>::\n+\tSet a symbolic mark for the last commit.\n+\t`<mark>` is an unsigned integer starting at 1 and\n+\tprefixed with a colon, e.g. `:1`.\n++\n+The marks can help if you want to refer to commits that you\n+created during the sequencer process, e.g. if you want to\n+merge such a commit.\n++\n+The set marks are removed after the sequencer has completed.\n+\n+\n+merge [options] <commit-ish1> <commit-ish2> ... <commit-ishN>::\n+\tMerge commits into HEAD.\n++\n+A commit can also be given by a mark, if prefixed with a colon.\n++\n+If you do not provide a commit message (using `-F`, `-m`, `-C`, `-M`,\n+or `--standard`), an editor will be invoked.\n++\n+See the following list and 'GENERAL OPTIONS' for values of `options`:\n+\n+\t--standard;;\n+\t\tGenerates a commit message like 'Merge ... into HEAD'.\n+\t\tSee also linkgit:git-fmt-merge-msg[1].\n+\n+\t-s <strategy>;;\n+\t--strategy=<strategy>;;\n+\t\tUse the given merge strategy.\n+\t\tSee also linkgit:git-merge[1].\n+\n+\n+pick [options] <commit>::\n+\tPick (see linkgit:git-cherry-pick[1]) a commit.\n+\tSequencer will pause on conflicts.\n++\n+See the following list and 'GENERAL OPTIONS' for values of `options`:\n+\n+\t-R;;\n+\t--reverse;;\n+\t\tRevert the changes introduced by pick <commit>.\n+\n+\t--mainline=<n>;;\n+\t\tAllows you to pick merge commits by specifying the\n+\t\tparent number (beginning from 1) to let sequencer\n+\t\treplay the changes relative to the specified parent.\n+\t\t+\n+This option does not work together with `-R`.\n+\n+\n+patch [options] <file>::\n+\tIf file `<file>` is a pure (diff) patch, then apply the patch.\n+\tIf no `--message` option is given, an editor will\n+\tbe invoked to enter a commit message.\n++\n+If `<file>` is a linkgit:git-format-patch[1]-formatted patch,\n+then the patch will be commited.\n++\n+See the following list and 'GENERAL OPTIONS' for values of `options`:\n+\n+\t-3;;\n+\t--3way;;\n+\t\tWhen the patch does not apply cleanly, fall back on\n+\t\t3-way merge, if the patch records the identity of blobs\n+\t\tit is supposed to apply to, and we have those blobs\n+\t\tavailable locally.\n+\n+\t-k;;\n+\t\tPass `-k` flag to `git-mailinfo` (see linkgit:git-mailinfo[1]).\n+\n+\t-n;;\n+\t\tPass `-n` flag to `git-mailinfo` (see linkgit:git-mailinfo[1]).\n+\n+\t-*;;\n+\t\tAny other dash-prefixed option is passed to\n+\t\tlinkgit:git-apply[1].\n+\t\tThis is especially useful for flags like\n+\t\t`--reverse`, `-C<n>`, `-p<n>` or `--whitespace=<action>`.\n+\n+\n+pause::\n+\tPauses the sequencer process to let you manually make changes.\n+\tFor example, you can re-edit the done commit, fix bugs or typos,\n+\tor you can make further commits on top of HEAD before continuing.\n++\n+After you have finished your changes and added them to the index,\n+invoke `git-sequencer --continue`.\n+If you only want to edit the last commit message with an editor,\n+run `git commit --amend` (see linkgit:git-commit[1]) before saying\n+`--continue`.\n+\n+\n+ref <ref>::\n+\tSet ref `<ref>` to the current HEAD, see also\n+\tlinkgit:git-update-ref[1].\n+\n+\n+reset <commit-ish>::\n+\tGo back (see linkgit:git-reset[1] `--hard`) to commit `<commit-ish>`.\n+\t`<commit-ish>` can also be given by a mark, if prefixed with a colon.\n+\n+\n+squash [options] <commit>::\n+\tAdd the changes introduced by `<commit>` to the last commit.\n++\n+See 'GENERAL OPTIONS' for values of `options`.\n+\n+squash [options] --from <mark>::\n+\tSquash all commits from the given mark into one commit.\n+\tThere must not be any `merge` instructions between the\n+\t`mark` instruction and this `squash --from` instruction.\n++\n+See the following list and 'GENERAL OPTIONS' for values of `options`:\n+\n+\t--collect-signoffs;;\n+\t\tCollect the Signed-off-by: lines of each commit and\n+\t\tadd them to the squashed commit message.\n+\t\t(Not yet implemented.)\n+\n+\t--include-merges;;\n+\t\tSanity check does not fail if you have merges\n+\t\tbetween HEAD and <mark>.\n+\n+\n+GENERAL OPTIONS\n+---------------\n+\n+Besides some special options, the instructions\n+`patch`, `merge`, `pick`, `squash` take the following general options:\n+\n+--author=<author>::\n+\tOverride the author name and e-mail address used in the commit.\n+\tUse `A U Thor <author@example.com>` format.\n+\n+-C <commit-ish>::\n+--reuse-commit=<commit-ish>::\n+\tReuse message and authorship data from specified commit.\n+\n+-M <commit-ish>\n+--reuse-message=<commit-ish>::\n+\tReuse message from specified commit.\n+\tNote, that only the commit message is reused\n+\tand not the authorship information.\n+\n+-F <file>::\n+--file=<file>::\n+\tTake the commit message from the given file.\n+\n+-m <msg>::\n+--message=<msg>::\n+\tUse the given `<msg>` as the commit message.\n+\n+--signoff::\n+\tAdd `Signed-off-by:` line to the commit message (if not yet there),\n+\tusing the committer identity of yourself.\n+\n+-e::\n+--edit::\n+\tRegardless what commit message options are given,\n+\tinvoke the editor to allow editing of the commit message.\n+\n+\n+RETURN VALUES\n+-------------\n+\n+git-sequencer returns:\n+\n+* `0`, if git-sequencer successfully completed all the instructions\n+       in the TODO file or successfully aborted after\n+       `git sequencer --abort`,\n+* `2`, on user-requested pausing, e.g.\n+       when using the `edit` instruction.\n+* `3`, on pauses that are not requested, e.g.\n+       when there are conflicts to resolve\n+       or errors in the TODO file.\n+* any other value on error, e.g.\n+  running git-sequencer on a bare repository.\n+\n+\n+EXAMPLES\n+--------\n+\n+TODO [Here the usage of all commands should become clear.]\n+\n+\n+SEE ALSO\n+--------\n+\n+linkgit:git-add[1],\n+linkgit:git-am[1],\n+linkgit:git-cherry-pick[1],\n+linkgit:git-commit[1],\n+linkgit:git-fmt-merge-msg[1],\n+linkgit:git-format-patch[1],\n+linkgit:git-rebase[1],\n+linkgit:git-reset[1],\n+linkgit:git-update-ref[1]\n+\n+\n+Authors\n+-------\n+Written by Stephan Beyer <s-beyer@gmx.net>.\n+\n+\n+Documentation\n+-------------\n+Documentation by Stephan Beyer and the git-list <git@vger.kernel.org>.\n+\n+GIT\n+---\n+Part of the linkgit:git[1] suite\n-- \n1.5.6.334.gdaf0\n"},{"id":"81826","messageId":"1214879914-17866-4-git-send-email-s-beyer@gmx.net","threadId":"14239","inReplyTo":"1214879914-17866-3-git-send-email-s-beyer@gmx.net","subject":"[RFC/PATCH 3/4] Add git-sequencer test suite (t3350)","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-01T02:38:33Z","receivedAt":"2008-07-01T02:38:33Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Mentored-by: Christian Couder <chriscool@tuxfamily.org>\nMentored-by: Daniel Barkalow <barkalow@iabervon.org>\nSigned-off-by: Stephan Beyer <s-beyer@gmx.net>\n---\nNote that the --quiet tests are test_expect_failure, because I\nhave not really cared about the output behavior of sequencer,\nand --quiet cannot be a trivial exec >/dev/null, because sometimes\neditors are invoked, etc.\n\nAlso note that the fake-editor is quite different from the one\nin the rebase tests.  According to a \"session\", the file is\ntotally rewritten. It's not possible to do something like\nFAKE_LINES=\"3 1 2\" so that the third line is the first one, etc.\n\n t/t3350-sequencer.sh |  810 ++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 810 insertions(+), 0 deletions(-)\n create mode 100755 t/t3350-sequencer.sh\n\ndiff --git a/t/t3350-sequencer.sh b/t/t3350-sequencer.sh\nnew file mode 100755\nindex 0000000..33522eb\n--- /dev/null\n+++ b/t/t3350-sequencer.sh\n@@ -0,0 +1,810 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2008 Stephan Beyer\n+#\n+# `setup' is based on t3404* by Johannes Schindelin.\n+\n+test_description='git sequencer\n+\n+These are basic usage tests for git sequencer.\n+'\n+. ./test-lib.sh\n+\n+# set up two branches like this:\n+#\n+# A - B - C - D - E\n+#   \\\n+#     F - G - H\n+#       \\\n+#         I\n+#\n+# where B, D and G touch increment value in file1.\n+# The others generate empty file[23456].\n+\n+SEQDIR=\".git/sequencer\"\n+SEQMARK=\"refs/sequencer-marks\"\n+MARKDIR=\".git/$SEQMARK\"\n+\n+test_expect_success 'setup' '\n+\t: >file1 &&\n+\tgit add file1 &&\n+\ttest_tick &&\n+\tgit commit -m \"generate empty file1\" &&\n+\tgit tag A &&\n+\techo 1 >file1 &&\n+\ttest_tick &&\n+\tgit commit -m \"write 1 into file1\" file1 &&\n+\tgit tag B &&\n+\t: >file2 &&\n+\tgit add file2 &&\n+\ttest_tick &&\n+\tgit commit -m \"generate empty file2\" &&\n+\tgit tag C &&\n+\techo 2 >file1 &&\n+\ttest_tick &&\n+\tgit commit -m \"write 2 into file1\" file1 &&\n+\tgit tag D &&\n+\t: >file3 &&\n+\tgit add file3 &&\n+\ttest_tick &&\n+\tgit commit -m \"generate empty file3\" &&\n+\tgit tag E &&\n+\tgit checkout -b branch1 A &&\n+\t: >file4 &&\n+\tgit add file4 &&\n+\ttest_tick &&\n+\tgit commit -m \"generate empty file4\" &&\n+\tgit tag F &&\n+\techo 3 >file1 &&\n+\ttest_tick &&\n+\tgit commit -m \"write 3 into file1\" file1 &&\n+\tgit tag G &&\n+\t: >file5 &&\n+\tgit add file5 &&\n+\ttest_tick &&\n+\tgit commit -m \"generate empty file5\" &&\n+\tgit tag H &&\n+\tgit checkout -b branch2 F &&\n+\t: >file6 &&\n+\tgit add file6 &&\n+\ttest_tick &&\n+\tgit commit -m \"generate empty file6\" &&\n+\tgit tag I &&\n+\tgit diff -p --raw C..D >patchD.raw &&\n+\tgit diff -p --raw A..F >patchF.raw &&\n+\tgit format-patch --stdout A..B >patchB &&\n+\tgit format-patch --stdout B..C >patchC &&\n+\tgit format-patch --stdout C..D >patchD &&\n+\tgit format-patch --stdout A..F >patchF &&\n+\tgit format-patch --stdout F..G >patchG\n+'\n+\n+orig_author=\"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\"\n+\n+# Functions to verify exit status of sequencer.\n+# Do not just use \"test_must_fail git sequencer ...\"!\n+expect_fail () {\n+\t\"$@\"\n+\ttest $? -eq 1\n+}\n+expect_continue () {\n+\t\"$@\"\n+\ttest $? -eq 2\n+}\n+expect_conflict () {\n+\t\"$@\"\n+\ttest $? -eq 3\n+}\n+\n+\n+# Other test helpers:\n+\n+# Test if commit $1 has author $2\n+expect_author () {\n+\ttest \"$2\" = \"$(git cat-file commit \"$1\" |\n+\t\tsed -n -e \"s/^author \\(.*\\)> .*$/\\1>/p\")\"\n+}\n+\n+# Test if commit $1 has commit message in file $2\n+# Side effect: overwrites actual\n+expect_msg () {\n+\tgit cat-file commit \"$1\" | sed -e \"1,/^$/d\" >actual &&\n+\ttest_cmp \"$2\" actual\n+}\n+\n+# Test that no marks are set.\n+no_marks_set () {\n+\tif test -e \"$MARKDIR\"\n+\tthen\n+\t\trmdir \"$MARKDIR\"\n+\tfi\n+}\n+\n+test_expect_success 'fail on empty TODO from stdin' '\n+\texpect_fail git sequencer <file6 &&\n+\t! test -d \"$SEQDIR\"\n+'\n+\n+# Generate fake editor\n+#\n+# Simple and practical concept:\n+#  We use only a small string identifier for \"editor sessions\".\n+#  Each sessions knows what to do and perhaps defines\n+#  which session to choose next.\n+echo \"#!$SHELL_PATH\" >fake-editor.sh\n+cat >>fake-editor.sh <<\\EOF\n+test -f fake-editor-session || exit 1\n+#test -t 1 || exit 1\n+# This test could be useful, but as the test-lib is not always\n+# verbose, this will fail.\n+next=ok\n+this=$(cat fake-editor-session)\n+case \"$this\" in\n+commitmsg)\n+\techo 'echo 2 >file1'\n+\t;;\n+squashCE)\n+\techo 'generate file2 and file3'\n+\t;;\n+squashCI)\n+\techo 'generate file2 and file6'\n+\tnext=squashDCE\n+\t;;\n+squashDCE)\n+\techo 'generate file2 and file3 and write 2 into file1'\n+\tnext=merge1\n+\t;;\n+merge1)\n+\techo 'A typed merge message.'\n+\t;;\n+merge2)\n+\ttest \"$(sed -n -e 1p \"$1\")\" = 'test merge' &&\n+\t\techo 'cleanup merge' ||\n+\t\techo error\n+\tsed -e 1d \"$1\"\n+\t;;\n+editXXXXXXXXX)\n+\tprintf 'last edited'\n+\t;;\n+edit*)\n+\tprintf 'edited: '\n+\tcat \"$1\"\n+\tnext=\"${this}X\"\n+\t;;\n+nochange)\n+\tcat \"$1\"\n+\t;;\n+ok|fail)\n+\techo '-- THIS IS UNEXPECTED --'\n+\tnext=fail\n+\t;;\n+*)\n+\techo 'I do not know.'\n+\t;;\n+esac >\"$1\".tmp\n+mv \"$1\".tmp \"$1\"\n+echo $next >fake-editor-session\n+exit 0\n+EOF\n+chmod a+x fake-editor.sh\n+test_set_editor \"$(pwd)/fake-editor.sh\"\n+\n+next_session () {\n+\techo \"$1\" >fake-editor-session\n+}\n+\n+# check if fake-editor-session is ok.\n+# If \"$1\" is set to anything, it will set the\n+# next session to \"ok\", which is nice for\n+# test_expect_failure.\n+session_ok () {\n+\ttest \"ok\" = $(cat fake-editor-session)\n+\tret=$?\n+\ttest -n \"$1\" && next_session ok\n+\treturn $ret\n+}\n+\n+\n+cat >todotest1 <<EOF\n+pick C\n+squash E\n+ref refs/tags/CE\n+EOF\n+\n+test_expect_success '\"pick\", \"squash\", \"ref\" from stdin' '\n+\tnext_session squashCE &&\n+\tgit sequencer <todotest1 &&\n+\t! test -d \"$SEQDIR\" &&\n+\tsession_ok &&\n+\ttest $(git rev-parse CE) = $(git rev-parse HEAD) &&\n+\ttest $(git rev-parse I) = $(git rev-parse HEAD^)\n+'\n+\n+cat >todotest2 <<EOF\n+# This is a test\n+\n+reset I  # go back to I\n+\n+EOF\n+\n+test_expect_success '\"reset\" from file with comments and blank lines' '\n+\tgit sequencer todotest2 &&\n+\tsession_ok &&\n+\ttest $(git rev-parse I) = $(git rev-parse HEAD)\n+'\n+\n+cat >todotest1 <<EOF\n+pick C\n+EOF\n+\n+test_expect_success '--onto <branch> keeps branch' '\n+\tgit checkout -b test-branch A &&\n+\tgit checkout master &&\n+\tgit sequencer --onto test-branch <todotest1 &&\n+\tsession_ok &&\n+\ttest \"$(git symbolic-ref -q HEAD)\" = \"refs/heads/test-branch\" &&\n+\ttest \"$(git rev-parse test-branch^)\" = \"$(git rev-parse A)\"\n+'\n+\n+test_expect_success '--onto commit (detached HEAD) works' '\n+\tgit sequencer --onto A <todotest1 &&\n+\tsession_ok &&\n+\ttest_must_fail git symbolic-ref -q HEAD &&\n+\ttest \"$(git rev-parse HEAD)\" = \"$(git rev-parse test-branch)\"\n+'\n+\n+echo 'pick -R C' >>todotest1\n+\n+test_expect_success 'pick -R works' '\n+\tgit checkout A &&\n+\tgit sequencer todotest1 &&\n+\tsession_ok &&\n+\t! test -f file2\n+'\n+\n+echo thisdoesnotexist >>todotest1\n+\n+test_expect_success 'junk is conflict' '\n+\tgit checkout A &&\n+\texpect_conflict git sequencer todotest1 &&\n+\ttest -d \"$SEQDIR\" &&\n+\tgit sequencer --abort &&\n+\t! test -d \"$SEQDIR\" &&\n+\tsession_ok &&\n+\ttest $(git rev-parse A) = $(git rev-parse HEAD)\n+'\n+\n+GIT_AUTHOR_NAME=\"Another Thor\"\n+GIT_AUTHOR_EMAIL=\"a.thor@example.com\"\n+GIT_COMMITTER_NAME=\"Co M Miter\"\n+GIT_COMMITTER_EMAIL=\"c.miter@example.com\"\n+export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL\n+yet_another=\"Max Min <mm@example.com>\"\n+\n+cat >todotest1 <<EOF\n+patch patchB      # write 1 into file1\n+patch -k patchC   # generate file2\n+patch patchD.raw  # write 2 into file1\n+EOF\n+\n+echo 'write 1 into file1' >expected1\n+echo '[PATCH] generate empty file2' >expected2\n+echo 'echo 2 >file1' >expected3\n+\n+test_expect_success '\"patch\" insn works' '\n+\tgit checkout A &&\n+\tnext_session commitmsg &&\n+\tgit sequencer todotest1 &&\n+\t! test -d \"$SEQDIR\" &&\n+\tsession_ok &&\n+\ttest \"$(git rev-parse HEAD~3)\" = \"$(git rev-parse A)\" &&\n+\ttest \"$(cat file1)\" = \"2\" &&\n+\ttest -z \"$(cat file2)\" &&\n+\texpect_author HEAD~2 \"$orig_author\" &&\n+\texpect_author HEAD~1 \"$orig_author\" &&\n+\texpect_author HEAD~0 \"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\" &&\n+\texpect_msg HEAD~2 expected1 &&\n+\texpect_msg HEAD~1 expected2 &&\n+\texpect_msg HEAD~0 expected3\n+'\n+\n+cat >todotest1 <<EOF\n+pick B\t# write 1 into file1\n+pause\n+pick C\t# generate file2\n+EOF\n+\n+echo 'generate empty file2' >expected1\n+echo 'write 1 into file1' >expected2\n+\n+test_expect_success \"pick ; pause insns and --continue works\" '\n+\tgit checkout A &&\n+\texpect_continue git sequencer todotest1 &&\n+\tsession_ok &&\n+\techo 5 >file1 &&\n+\tgit add file1 &&\n+\tnext_session nochange &&\n+\tgit sequencer --continue &&\n+\ttest \"$(cat file1)\" = 5 &&\n+\ttest -z \"$(cat file2)\" &&\n+\texpect_msg HEAD expected1 &&\n+\texpect_msg HEAD^ expected2 &&\n+\tsession_ok\n+'\n+\n+cat >todotest1 <<EOF\n+edit B\t# write 1 into file1\n+pick C\t# generate file2\n+EOF\n+\n+test_expect_success \"edit insn and --continue works\" '\n+\tgit checkout A &&\n+\texpect_continue git sequencer todotest1 &&\n+\tsession_ok &&\n+\techo 5 >file1 &&\n+\tgit add file1 &&\n+\tnext_session nochange &&\n+\tgit sequencer --continue &&\n+\ttest \"$(cat file1)\" = 5 &&\n+\ttest -z \"$(cat file2)\" &&\n+\texpect_msg HEAD expected1 &&\n+\texpect_msg HEAD^ expected2 &&\n+\tsession_ok\n+'\n+\n+cat >todotest1 <<EOF\n+patch patchB\t# write 1 into file1\n+pick H\t\t# generate file5\n+mark :1\n+patch patchC\t# generate file2\n+squash I\t# generate file6\n+patch patchD\t# write 2 into file1\n+ref refs/tags/CID\n+mark :2\n+reset :1\t# reset to new H\n+patch patchD\t# write 2 into file1\n+squash CE\t# generate file2 and file3\n+ref refs/tags/DCE\n+merge :2\t# merge :2 into HEAD\n+patch patchF\t# generate file4\n+EOF\n+\n+test_expect_success 'all insns work without options' '\n+\tgit checkout A &&\n+\tnext_session squashCI &&\n+\tno_marks_set &&\n+\tgit sequencer todotest1 &&\n+\tno_marks_set &&\n+\ttest \"$(cat file1)\" = \"2\" &&\n+\ttest -z \"$(cat file2)\" &&\n+\ttest -z \"$(cat file3)\" &&\n+\ttest -z \"$(cat file4)\" &&\n+\ttest -z \"$(cat file5)\" &&\n+\ttest -z \"$(cat file6)\" &&\n+\techo \"$(git rev-parse DCE)\" >expected &&\n+\techo \"$(git rev-parse CID)\" >>expected &&\n+\tgit cat-file commit HEAD^ | sed -n -e \"s/^parent //p\" >actual &&\n+\ttest_cmp expected actual &&\n+\tsession_ok\n+'\n+\n+cat >todotest1 <<EOF\n+merge --standard DCE\n+EOF\n+\n+echo \"Merge DCE into HEAD\" >expected1\n+\n+test_expect_success 'merge --standard works' '\n+\tgit checkout CID &&\n+\tgit sequencer todotest1 &&\n+\texpect_msg HEAD expected1 &&\n+\tsession_ok\n+'\n+\n+cat >todotest1 <<EOF\n+merge --standard --message=\"foo\" DCE\n+EOF\n+\n+\n+test_expect_success 'merge --standard --message=\"foo\" is conflict' '\n+\tgit checkout CID &&\n+\texpect_conflict git sequencer todotest1 &&\n+\tgit sequencer --abort &&\n+\tsession_ok\n+'\n+\n+for command in 'pick ' 'patch patch' 'squash ' 'merge --standard '\n+do\n+\tcat >todotest1 <<EOF\n+patch patchB\t# 1 into file1\n+${command}G\t# 3 into file1\n+patch -3 patchF\t# empty file4\n+EOF\n+\n+\ttest_expect_success \"conflict test: ${command%% *} and --abort\" '\n+\t\tgit checkout A &&\n+\t\texpect_conflict git sequencer todotest1 &&\n+\t\tsession_ok &&\n+\t\ttest -d \"$SEQDIR\" &&\n+\t\tgit sequencer --abort &&\n+\t\tsession_ok &&\n+\t\ttest $(git rev-parse HEAD) = $(git rev-parse A)\n+\t'\n+\n+\ttest_expect_success \"conflict test: ${command%% *} and --continue\" '\n+\t\tgit checkout A &&\n+\t\texpect_conflict git sequencer todotest1 &&\n+\t\tsession_ok &&\n+\t\ttest -d \"$SEQDIR\" &&\n+\t\t## XXX: It would be perfect if we could remove the if\n+\t\t{ if test \"${command%% *}\" != \"patch\"\n+\t\tthen grep -q \"^<<<<<<<\" file1 ; fi } &&\n+\t\techo 3 >file1 &&\n+\t\tgit add file1 &&\n+\t\tnext_session nochange &&\n+\t\tgit sequencer --continue &&\n+\t\tsession_ok &&\n+\t\t! test -d \"$SEQDIR\" &&\n+\t\ttest \"$(cat file1)\" = \"3\" &&\n+\t\ttest -f file4\n+\t'\n+\n+\ttest_expect_success \"conflict test: ${command%% *} and --skip\" '\n+\t\tgit checkout A &&\n+\t\texpect_conflict git sequencer todotest1 &&\n+\t\tsession_ok &&\n+\t\ttest -d \"$SEQDIR\" &&\n+\t\tgit sequencer --skip &&\n+\t\tsession_ok &&\n+\t\t! test -d \"$SEQDIR\" &&\n+\t\ttest \"$(cat file1)\" = \"1\" &&\n+\t\ttest -f file4\n+\t'\n+done\n+\n+echo 'file5-gen' >commitmsg\n+\n+cat >todotest1 <<EOF\n+patch --signoff patchB\n+pause\n+pick --author=\"$yet_another\" --file=\"commitmsg\" --signoff H\n+mark :1\n+patch --message=\"file2-gen\" patchC\n+squash --signoff --author=\"$yet_another\" I\n+pause\n+patch --message=\"echo 2 >file1\" patchD\n+mark :2\n+reset :1\n+patch --author=\"$yet_another\" patchD\n+squash --signoff --message=\"generate file[23]\" CE\n+merge --signoff --message=\"test merge\" --author=\"$yet_another\" :2\n+pause\n+ref refs/tags/a_merge\n+patch --message=\"Generate file4 and write 23 into it\" patchF.raw\n+pause\n+pick I\n+EOF\n+\n+cat >expected1 <<EOF\n+write 1 into file\n+\n+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n+EOF\n+\n+test_expect_success 'insns work with options and another author 1' '\n+\tgit checkout A &&\n+\tno_marks_set &&\n+\n+\t# patch --signoff patchB  # write 1 into file1\n+\t# pause\n+\texpect_continue git sequencer todotest1 &&\n+\ttest \"Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\" = \\\n+\t\t\"$(git cat-file commit HEAD | grep \"^Signed-off-by\")\" &&\n+\texpect_author HEAD \"$orig_author\" &&\n+\ttest -d \"$SEQDIR\" &&\n+\tsession_ok\n+'\n+\n+cat >expected1 <<EOF\n+file5-gen\n+\n+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n+EOF\n+\n+cat >expected2 <<EOF\n+file2-gen\n+\n+generate empty file6\n+\n+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n+EOF\n+\n+test_expect_success 'insns work with options and another author 2' '\n+\t: >file7 &&\n+\tgit add file7 &&\n+\tnext_session nochange &&\n+\tgit commit --amend &&\n+\tsession_ok &&\n+\n+\tnext_session nochange &&\n+\texpect_continue git sequencer --continue &&\n+\tsession_ok &&\n+\n+\t# amended commit\n+\ttest \"Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\" = \\\n+\t\t\"$(git cat-file commit HEAD^^ | grep \"^Signed-off-by\")\" &&\n+\texpect_author HEAD^^ \"$orig_author\" &&\n+\ttest -z \"$(cat file7)\" &&\n+\n+\t# pick --author=\"$yet_another\" --file=\"commitmsg\" --signoff H\n+\texpect_author HEAD^ \"$yet_another\" &&\n+\texpect_msg HEAD^ expected1 &&\n+\ttest -z \"$(cat file5)\" &&\n+\n+\t# mark :1\n+\ttest \"$(git rev-parse \"$SEQMARK/1\")\" = \"$(git rev-parse HEAD^)\" &&\n+\n+\t# patch --message=\"file2-gen\" patchC\n+\t# squash --signoff --author=\"$yet_another\" I # generate file6\n+\t# pause\n+\ttest -z \"$(cat file2)\" &&\n+\ttest -z \"$(cat file6)\" &&\n+\tgit ls-files | grep -q \"^file2\" &&\n+\tgit ls-files | grep -q \"^file6\" &&\n+\texpect_msg HEAD expected2 &&\n+\texpect_author HEAD \"$yet_another\"\n+'\n+\n+echo 'echo 2 >file1' >expected1\n+\n+cat >expected2 <<EOF\n+generate file[23]\n+\n+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n+EOF\n+\n+cat >expected3 <<EOF\n+test merge\n+\n+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n+EOF\n+\n+cat >expected4 <<EOF\n+file1\n+file2\n+file3\n+file5\n+file6\n+file7\n+EOF\n+\n+test_expect_success 'insns work with options and another author 3' '\n+\t# do not change anything\n+\texpect_continue git sequencer --continue &&\n+\tsession_ok &&\n+\n+\t# patch --message=\"echo 2 >file1\" patchD\n+\t# mark :2\n+\tcommit=\"$(git rev-parse --verify \"$SEQMARK/2\")\" &&\n+\texpect_author \"$commit\" \"$orig_author\" &&\n+\texpect_msg \"$commit\" expected1 &&\n+\n+\t# reset :1\n+\t# patch --author=\"$yet_another\" patchD # write 2 into file1\n+\t# squash --signoff --message=\"generate file[23]\" CE\n+\texpect_author HEAD^ \"$yet_another\" &&\n+\texpect_msg HEAD^ expected2 &&\n+\n+\t# merge --signoff --message=\"test merge\" --author=\"$yet_another\" :2\n+\t# pause\n+\texpect_author HEAD \"$yet_another\" &&\n+\texpect_msg HEAD expected3 &&\n+\tgit ls-files >actual &&\n+\ttest_cmp expected4 actual\n+'\n+\n+cat >expected_merge <<EOF\n+cleanup merge\n+\n+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n+EOF\n+\n+echo 'Generate file4 and write 23 into it' >expected2\n+\n+test_expect_success 'insns work with options and another author 4' '\n+\tgit rm file5 file6 file7 &&\n+\tnext_session merge2 &&\n+\texpect_continue git sequencer --continue &&\n+\tsession_ok &&\n+\n+\t# ref refs/tags/a_merge\n+\texpect_author a_merge \"$yet_another\" &&\n+\texpect_msg a_merge expected_merge &&\n+\n+\t# patch --message=\"Generate file4 and write 23 into it\" patchF.raw\n+\t# pause\n+\tgit ls-files | grep -q \"^file4\" &&\n+\techo 23 >file4 &&\n+\tgit add file4 &&\n+\tnext_session nochange &&\n+\tgit sequencer --continue &&\n+\tsession_ok &&\n+\tno_marks_set &&\n+\ttest \"$(cat file1)\" = \"2\" &&\n+\ttest \"$(cat file4)\" = \"23\" &&\n+\texpect_msg HEAD^ expected2 &&\n+\texpect_author HEAD^ \"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\" &&\n+\n+\t# pick I\n+\ttest -z \"$(cat file6)\" &&\n+\tgit ls-files | grep -q \"^file6\" &&\n+\tsession_ok\n+'\n+\n+# almost the same to test --quiet\n+cat >todotest1 <<EOF\n+patch patchB\n+pick H\n+mark :1\n+patch patchC\n+squash --message=\"a squash\" I\n+patch patchD\n+mark :2\n+reset :1\n+patch patchD\n+squash --message=\"another squash\" CE\n+merge --message=\"test merge\" :2\n+pause\n+patch patchF\n+EOF\n+\n+test_expect_failure '--quiet works' '\n+\tgit checkout A &&\n+\texpect_continue git sequencer --quiet todotest1 >actual &&\n+\tsession_ok &&\n+\t! test -s actual\n+'\n+\n+test_expect_failure '--quiet works on continue' '\n+\tgit sequencer --continue >>actual &&\n+\tsession_ok &&\n+\t! test -s actual\n+'\n+\n+echo 'merge --strategy=ours --reuse-commit=a_merge branch1 branch2 CE CID' >todotest1\n+\n+test_expect_success 'merge multiple branches and --reuse-commit works' '\n+\tgit checkout -b merge-multiple master &&\n+\tgit sequencer todotest1 &&\n+\tsession_ok &&\n+\texpect_msg HEAD expected_merge &&\n+\tgit rev-parse HEAD^ >expected &&\n+\tgit rev-parse branch1 >>expected &&\n+\tgit rev-parse branch2 >>expected &&\n+\tgit rev-parse CE >>expected &&\n+\tgit rev-parse CID >>expected &&\n+\tgit cat-file commit HEAD | sed -n -e \"s/^parent //p\" >actual &&\n+\ttest_cmp expected actual &&\n+\t! test -f file6\n+'\n+\n+echo 'pick --mainline=5 merge-multiple' >todotest1\n+\n+test_expect_success 'pick --mainline works' '\n+\tgit checkout -b mainline CID &&\n+\tgit sequencer todotest1 &&\n+\tsession_ok &&\n+\texpect_msg HEAD expected_merge &&\n+\t! test -f file6 &&\n+\ttest -f file3 &&\n+\ttest -f file2 &&\n+\ttest \"$(cat file1)\" = 2\n+'\n+\n+cat >todotest1 <<EOF\n+pick C\t\t# file2\n+mark :1\n+patch patchB\t# write 1 into file1\n+patch patchD\t# write 2 into file1\n+pick I\t\t# file6\n+squash --message=\"2 in file1 and file6 exists\" --signoff --from :1\n+EOF\n+\n+cat >expected1 <<EOF\n+2 in file1 and file6 exists\n+\n+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>\n+EOF\n+\n+test_expect_success 'squash --from works' '\n+\tgit checkout A &&\n+\tgit sequencer <todotest1 &&\n+\tsession_ok &&\n+\ttest \"$(git rev-parse A)\" = \"$(git rev-parse HEAD~2)\" &&\n+\ttest \"$(cat file1)\" = \"2\" &&\n+\ttest -z \"$(cat file6)\" &&\n+\texpect_msg HEAD expected1\n+'\n+\n+cat >todotest1 <<EOF\n+patch patchB\t# write 1 into file1\n+pick H\t\t# generate file5\n+mark :1\n+patch patchC\t# generate file2\n+squash --message=\"file5\" I\t# generate file6\n+patch patchD\t# write 2 into file1\n+mark :2\n+reset :1\t# reset to new H\n+patch patchD\t# write 2 into file1\n+squash --message=\"CE\" CE\t# generate file2 and file3\n+merge --standard :2\t# merge :2 into HEAD\n+patch patchF\t# generate file4\n+EOF\n+cp todotest1 todotest2\n+cat todotest1 | sed -e 's/^\\(patch\\|pick\\|squash\\|merge\\) /&--edit /' >todotest3\n+echo 'squash --message=\"doesnt work either\" --from :1' >>todotest1\n+echo 'squash --include-merges --message=\"stupid\" --from :1' >>todotest2\n+\n+test_expect_success 'squash --from conflicts with merge in between' '\n+\tgit checkout A &&\n+\texpect_conflict git sequencer todotest1 &&\n+\tgit sequencer --abort &&\n+\tsession_ok &&\n+\t! test -d \"$SEQDIR\"\n+'\n+\n+test_expect_success 'squash --include-merges --from succeeds with merge in between' '\n+\tgit checkout A &&\n+\tgit sequencer todotest2 &&\n+\tsession_ok &&\n+\ttest \"$(git rev-parse HEAD~3)\" = \"$(git rev-parse A)\"\n+'\n+\n+test_expect_success 'patch|pick|squash|merge --edit works' '\n+\tgit checkout A &&\n+\tnext_session editX &&\n+\tgit sequencer todotest3 &&\n+\tsession_ok\n+'\n+\n+cat >todotest1 <<EOF\n+patch patchB\n+pause\n+EOF\n+\n+test_expect_success 'batch mode fails on pause insn' '\n+\tgit checkout A &&\n+\texpect_fail git sequencer --batch todotest1 &&\n+\tsession_ok &&\n+\t! test -d \"$SEQDIR\"\n+'\n+\n+cat >todotest1 <<EOF\n+patch patchB\n+pick G\n+EOF\n+\n+test_expect_success 'batch mode fails on conflict' '\n+\tgit checkout A &&\n+\texpect_fail git sequencer --batch <todotest1 &&\n+\tsession_ok &&\n+\t! test -d \"$SEQDIR\" &&\n+\ttest -z $(cat file1)\n+'\n+\n+cat >todotest1 <<EOF\n+patch patchB\n+pause\n+EOF\n+\n+test_expect_success '--caller works' '\n+\tgit checkout A &&\n+\texpect_continue git sequencer \\\n+\t\t--caller=\"this works|abrt||skip\" todotest1 &&\n+\texpect_fail git sequencer --abort &&\n+\texpect_fail git sequencer --skip &&\n+\tgit sequencer --continue &&\n+\tsession_ok\n+'\n+\n+test_done\n-- \n1.5.6.334.gdaf0\n"},{"id":"81825","messageId":"1214879914-17866-5-git-send-email-s-beyer@gmx.net","threadId":"14239","inReplyTo":"1214879914-17866-4-git-send-email-s-beyer@gmx.net","subject":"[RFC/PATCH 4/4] Migrate git-am to use git-sequencer","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-01T02:38:34Z","receivedAt":"2008-07-01T02:38:34Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"This patch also adds --abort to git-am, which is just a\ntrivial implication of using git-sequencer.\n\nSigned-off-by: Stephan Beyer <s-beyer@gmx.net>\n---\nHm, what to say here?\n\nI have to admit that interactive mode is purely tested.\nWell, I've used sequencer-based git-am for a while, but never really\nused the interactive mode (except for first manual test cases).\n\n Documentation/git-am.txt |    5 +-\n git-am.sh                |  552 +++++++++++++---------------------------------\n git-rebase.sh            |    7 +-\n t/t3407-rebase-abort.sh  |   10 +-\n t/t4150-am.sh            |   21 ++-\n 5 files changed, 178 insertions(+), 417 deletions(-)\n\ndiff --git a/Documentation/git-am.txt b/Documentation/git-am.txt\nindex 46544a0..b714106 100644\n--- a/Documentation/git-am.txt\n+++ b/Documentation/git-am.txt\n@@ -13,7 +13,7 @@ SYNOPSIS\n          [--3way] [--interactive] [--binary]\n          [--whitespace=<option>] [-C<n>] [-p<n>]\n          <mbox>|<Maildir>...\n-'git-am' [--skip | --resolved]\n+'git-am' (--abort | --skip | --resolved)\n \n DESCRIPTION\n -----------\n@@ -79,6 +79,9 @@ default.   You could use `--no-utf8` to override this.\n --interactive::\n \tRun interactively.\n \n+--abort::\n+\tAbort applying and rewind applied patches.\n+\n --skip::\n \tSkip the current patch.  This is only meaningful when\n \trestarting an aborted patch.\ndiff --git a/git-am.sh b/git-am.sh\nindex 2c517ed..dd19dd7 100755\n--- a/git-am.sh\n+++ b/git-am.sh\n@@ -6,9 +6,11 @@ SUBDIRECTORY_OK=Yes\n OPTIONS_KEEPDASHDASH=\n OPTIONS_SPEC=\"\\\n git-am [options] <mbox>|<Maildir>...\n+git-am [options] --abort\n git-am [options] --resolved\n git-am [options] --skip\n --\n+abort           abort patching and reset done patches\n d,dotest=       (removed -- do not use)\n i,interactive   run interactively\n b,binary        pass --allow-binary-replacement to git-apply\n@@ -30,104 +32,101 @@ set_reflog_action am\n require_work_tree\n cd_to_toplevel\n \n-git var GIT_COMMITTER_IDENT >/dev/null || exit\n+git var GIT_COMMITTER_IDENT >/dev/null ||\n+\tdie \"You need to set your committer info first\"\n \n-stop_here () {\n-    echo \"$1\" >\"$dotest/next\"\n-    exit 1\n+cleanup () {\n+\tgit gc --auto\n+\trm -fr \"$dotest\"\n }\n \n-stop_here_user_resolve () {\n-    if [ -n \"$resolvemsg\" ]; then\n-\t    printf '%s\\n' \"$resolvemsg\"\n-\t    stop_here $1\n-    fi\n-    cmdline=$(basename $0)\n-    if test '' != \"$interactive\"\n-    then\n-        cmdline=\"$cmdline -i\"\n-    fi\n-    if test '' != \"$threeway\"\n-    then\n-        cmdline=\"$cmdline -3\"\n-    fi\n-    echo \"When you have resolved this problem run \\\"$cmdline --resolved\\\".\"\n-    echo \"If you would prefer to skip this patch, instead run \\\"$cmdline --skip\\\".\"\n-\n-    stop_here $1\n+die_abort () {\n+\tcleanup\n+\tdie \"$1\"\n }\n \n-go_next () {\n-\trm -f \"$dotest/$msgnum\" \"$dotest/msg\" \"$dotest/msg-clean\" \\\n-\t\t\"$dotest/patch\" \"$dotest/info\"\n-\techo \"$next\" >\"$dotest/next\"\n-\tthis=$next\n-}\n+be_interactive () {\n+\tmsg=\"$GIT_DIR/sequencer/message\"\n+\tpatch=\"$GIT_DIR/sequencer/patch\"\n+\tauthor_script=\"$GIT_DIR/sequencer/author-script\"\n+\t# we rely on sequencer here\n+\n+\ttest -t 0 ||\n+\t\tdie \"cannot be interactive without stdin connected to a terminal.\"\n+\taction=$(cat \"$dotest/interactive\")\n+\twhile test \"$action\" = again\n+\tdo\n+\t\techo \"Commit Body is:\"\n+\t\techo \"--------------------------\"\n+\t\tcat \"$msg\"\n+\t\techo \"--------------------------\"\n+\t\tprintf \"Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all \"\n \n-cannot_fallback () {\n-\techo \"$1\"\n-\techo \"Cannot fall back to three-way merge.\"\n-\texit 1\n+\t\tread reply\n+\t\tcase \"$reply\" in\n+\t\t[yY]*)\n+\t\t\trun_sequencer --continue\n+\t\t\t;;\n+\t\t[nN]*)\n+\t\t\tgit reset --hard HEAD^\n+\t\t\trun_sequencer --continue\n+\t\t\t;;\n+\t\t[eE]*)\n+\t\t\tgit_editor \"$msg\"\n+\t\t\tgit commit --amend --file=\"$msg\" --no-verify >/dev/null\n+\t\t\t;;\n+\t\t[vV]*)\n+\t\t\tLESS=-S ${PAGER:-less} \"$patch\"\n+\t\t\t;;\n+\t\t[aA]*)\n+\t\t\techo 'accept' >\"$dotest/interactive\"\n+\t\t\trun_sequencer --continue\n+\t\t\t;;\n+\t\t*)\n+\t\t\t:\n+\t\t\t;;\n+\t\tesac\n+\tdone\n+\ttest \"$action\" = accept &&\n+\t\trun_sequencer --continue\n }\n \n-fall_back_3way () {\n-    O_OBJECT=`cd \"$GIT_OBJECT_DIRECTORY\" && pwd`\n-\n-    rm -fr \"$dotest\"/patch-merge-*\n-    mkdir \"$dotest/patch-merge-tmp-dir\"\n-\n-    # First see if the patch records the index info that we can use.\n-    git apply --build-fake-ancestor \"$dotest/patch-merge-tmp-index\" \\\n-\t\"$dotest/patch\" &&\n-    GIT_INDEX_FILE=\"$dotest/patch-merge-tmp-index\" \\\n-    git write-tree >\"$dotest/patch-merge-base+\" ||\n-    cannot_fallback \"Repository lacks necessary blobs to fall back on 3-way merge.\"\n-\n-    echo Using index info to reconstruct a base tree...\n-    if GIT_INDEX_FILE=\"$dotest/patch-merge-tmp-index\" \\\n-\tgit apply $binary --cached <\"$dotest/patch\"\n-    then\n-\tmv \"$dotest/patch-merge-base+\" \"$dotest/patch-merge-base\"\n-\tmv \"$dotest/patch-merge-tmp-index\" \"$dotest/patch-merge-index\"\n-    else\n-        cannot_fallback \"Did you hand edit your patch?\n-It does not apply to blobs recorded in its index.\"\n-    fi\n-\n-    test -f \"$dotest/patch-merge-index\" &&\n-    his_tree=$(GIT_INDEX_FILE=\"$dotest/patch-merge-index\" git write-tree) &&\n-    orig_tree=$(cat \"$dotest/patch-merge-base\") &&\n-    rm -fr \"$dotest\"/patch-merge-* || exit 1\n-\n-    echo Falling back to patching base and 3-way merge...\n-\n-    # This is not so wrong.  Depending on which base we picked,\n-    # orig_tree may be wildly different from ours, but his_tree\n-    # has the same set of wildly different changes in parts the\n-    # patch did not touch, so recursive ends up canceling them,\n-    # saying that we reverted all those changes.\n \n-    eval GITHEAD_$his_tree='\"$FIRSTLINE\"'\n-    export GITHEAD_$his_tree\n-    git-merge-recursive $orig_tree -- HEAD $his_tree || {\n-\t    git rerere\n-\t    echo Failed to merge in the changes.\n-\t    exit 1\n-    }\n-    unset GITHEAD_$his_tree\n+run_sequencer () {\n+\tgit sequencer --caller='git am|--abort|--resolved|--skip' \"$@\"\n+\tcase \"$?\" in\n+\t0)\n+\t\tcleanup\n+\t\texit 0\n+\t\t;;\n+\t2)\n+\t\ttest -n \"$interactive\" && be_interactive\n+\t\techo 'git-sequencer needs continuation (by edit).'\n+\t\texit 0\n+\t\t;;\n+\t3)\n+\t\tdie 'git-sequencer needs continuation (by conflict).'\n+\t\t;;\n+\t*)\n+\t\tdie_abort 'git-sequencer died.'\n+\t\t;;\n+\tesac\n }\n \n prec=4\n dotest=\".dotest\"\n+todofile=\"$dotest/todo\"\n sign= utf8=t keep= skip= interactive= resolved= binary= rebasing=\n-resolvemsg= resume=\n-git_apply_opt=\n+resolvemsg=\n+opts=\n \n while test $# != 0\n do\n \tcase \"$1\" in\n \t-i|--interactive)\n-\t\tinteractive=t ;;\n+\t\tinteractive=-q ;;\n+\t--abort)\n+\t\tabort=t ;;\n \t-b|--binary)\n \t\tbinary=t ;;\n \t-3|--3way)\n@@ -152,9 +151,9 @@ do\n \t--resolvemsg)\n \t\tshift; resolvemsg=$1 ;;\n \t--whitespace)\n-\t\tgit_apply_opt=\"$git_apply_opt $1=$2\"; shift ;;\n+\t\topts=\"$opts $1=$2\"; shift ;;\n \t-C|-p)\n-\t\tgit_apply_opt=\"$git_apply_opt $1$2\"; shift ;;\n+\t\topts=\"$opts $1$2\"; shift ;;\n \t--)\n \t\tshift; break ;;\n \t*)\n@@ -163,347 +162,92 @@ do\n \tshift\n done\n \n-# If the dotest directory exists, but we have finished applying all the\n-# patches in them, clear it out.\n-if test -d \"$dotest\" &&\n-   last=$(cat \"$dotest/last\") &&\n-   next=$(cat \"$dotest/next\") &&\n-   test $# != 0 &&\n-   test \"$next\" -gt \"$last\"\n-then\n-   rm -fr \"$dotest\"\n-fi\n-\n if test -d \"$dotest\"\n then\n-\tcase \"$#,$skip$resolved\" in\n-\t0,*t*)\n-\t\t# Explicit resume command and we do not have file, so\n-\t\t# we are happy.\n-\t\t: ;;\n-\t0,)\n-\t\t# No file input but without resume parameters; catch\n-\t\t# user error to feed us a patch from standard input\n-\t\t# when there is already $dotest.  This is somewhat\n-\t\t# unreliable -- stdin could be /dev/null for example\n-\t\t# and the caller did not intend to feed us a patch but\n-\t\t# wanted to continue unattended.\n-\t\ttty -s\n-\t\t;;\n-\t*)\n-\t\tfalse\n-\t\t;;\n-\tesac ||\n-\tdie \"previous dotest directory $dotest still exists but mbox given.\"\n-\tresume=yes\n-else\n-\t# Make sure we are not given --skip nor --resolved\n-\ttest \",$skip,$resolved,\" = ,,, ||\n-\t\tdie \"Resolve operation not in progress, we are not resuming.\"\n+\ttest \"$#\" != 0 &&\n+\t\tdie \"previous dotest directory $dotest still exists but mbox given.\"\n+\n+\ttest -f \"$dotest/interactive\" &&\n+\t\tinteractive=-q action=$(cat \"$dotest/interactive\")\n \n-\t# Start afresh.\n-\tmkdir -p \"$dotest\" || exit\n+\t# No file input but without resume parameters; catch\n+\t# user error to feed us a patch from standard input\n+\t# when there is already $dotest.  This is somewhat\n+\t# unreliable -- stdin could be /dev/null for example\n+\t# and the caller did not intend to feed us a patch but\n+\t# wanted to continue unattended.\n+\ttest -z \"$abort$resolved$skip\" && tty -s\n \n-\tif test -n \"$prefix\" && test $# != 0\n-\tthen\n-\t\tfirst=t\n-\t\tfor arg\n-\t\tdo\n-\t\t\ttest -n \"$first\" && {\n-\t\t\t\tset x\n-\t\t\t\tfirst=\n-\t\t\t}\n-\t\t\tcase \"$arg\" in\n-\t\t\t/*)\n-\t\t\t\tset \"$@\" \"$arg\" ;;\n-\t\t\t*)\n-\t\t\t\tset \"$@\" \"$prefix$arg\" ;;\n-\t\t\tesac\n-\t\tdone\n-\t\tshift\n-\tfi\n-\tgit mailsplit -d\"$prec\" -o\"$dotest\" -b -- \"$@\" > \"$dotest/last\" ||  {\n-\t\trm -fr \"$dotest\"\n-\t\texit 1\n-\t}\n+\ttest -n \"$abort\" && run_sequencer --abort\n+\ttest -n \"$resolved\" && run_sequencer --continue\n+\ttest -n \"$skip\" && run_sequencer --skip\n \n-\t# -b, -s, -u, -k and --whitespace flags are kept for the\n-\t# resuming session after a patch failure.\n-\t# -3 and -i can and must be given when resuming.\n-\techo \"$binary\" >\"$dotest/binary\"\n-\techo \" $ws\" >\"$dotest/whitespace\"\n-\techo \"$sign\" >\"$dotest/sign\"\n-\techo \"$utf8\" >\"$dotest/utf8\"\n-\techo \"$keep\" >\"$dotest/keep\"\n-\techo 1 >\"$dotest/next\"\n-\tif test -n \"$rebasing\"\n-\tthen\n-\t\t: >\"$dotest/rebasing\"\n-\telse\n-\t\t: >\"$dotest/applying\"\n-\tfi\n+\tdie \"$dotest still exists. Use git am --abort/--skip/--resolved.\"\n fi\n \n-case \"$resolved\" in\n-'')\n-\tfiles=$(git diff-index --cached --name-only HEAD --) || exit\n-\tif [ \"$files\" ]; then\n-\t   echo \"Dirty index: cannot apply patches (dirty: $files)\" >&2\n-\t   exit 1\n-\tfi\n-esac\n+# Make sure we are not given --skip nor --resolved nor --abort\n+test -z \"$abort$resolved$skip\" ||\n+\tdie 'git-am is not in progress. You cannot use --abort/--skip/--resolved then.'\n \n-if test \"$(cat \"$dotest/binary\")\" = t\n-then\n-\tbinary=--allow-binary-replacement\n-fi\n-if test \"$(cat \"$dotest/utf8\")\" = t\n-then\n-\tutf8=-u\n-else\n-\tutf8=-n\n-fi\n-if test \"$(cat \"$dotest/keep\")\" = t\n-then\n-\tkeep=-k\n-fi\n-ws=`cat \"$dotest/whitespace\"`\n-if test \"$(cat \"$dotest/sign\")\" = t\n-then\n-\tSIGNOFF=`git-var GIT_COMMITTER_IDENT | sed -e '\n-\t\t\ts/>.*/>/\n-\t\t\ts/^/Signed-off-by: /'\n-\t\t`\n-else\n-\tSIGNOFF=\n-fi\n+# Start afresh.\n+mkdir -p \"$dotest\" ||\n+\tdie \"Could not create $dotest directory.\"\n \n-last=`cat \"$dotest/last\"`\n-this=`cat \"$dotest/next\"`\n-if test \"$skip\" = t\n+if test -n \"$prefix\" && test $# != 0\n then\n-\tgit rerere clear\n-\tthis=`expr \"$this\" + 1`\n-\tresume=\n+\tfirst=t\n+\tfor arg\n+\tdo\n+\t\ttest -n \"$first\" && {\n+\t\t\tset x\n+\t\t\tfirst=\n+\t\t}\n+\t\tcase \"$arg\" in\n+\t\t/*)\n+\t\t\tset \"$@\" \"$arg\" ;;\n+\t\t*)\n+\t\t\tset \"$@\" \"$prefix$arg\" ;;\n+\t\tesac\n+\tdone\n+\tshift\n fi\n+last=$(git mailsplit -d\"$prec\" -o\"$dotest\" -b -- \"$@\") ||  {\n+\tcleanup\n+\texit 1\n+}\n+this=1\n \n-if test \"$this\" -gt \"$last\"\n-then\n-\techo Nothing to do.\n-\trm -fr \"$dotest\"\n-\texit\n+files=$(git diff-index --cached --name-only HEAD --) || exit\n+if [ \"$files\" ]; then\n+\techo \"Dirty index: cannot apply patches (dirty: $files)\" >&2\n+\texit 1\n fi\n \n-while test \"$this\" -le \"$last\"\n-do\n-\tmsgnum=`printf \"%0${prec}d\" $this`\n-\tnext=`expr \"$this\" + 1`\n-\ttest -f \"$dotest/$msgnum\" || {\n-\t\tresume=\n-\t\tgo_next\n-\t\tcontinue\n-\t}\n-\n-\t# If we are not resuming, parse and extract the patch information\n-\t# into separate files:\n-\t#  - info records the authorship and title\n-\t#  - msg is the rest of commit log message\n-\t#  - patch is the patch body.\n-\t#\n-\t# When we are resuming, these files are either already prepared\n-\t# by the user, or the user can tell us to do so by --resolved flag.\n-\tcase \"$resume\" in\n-\t'')\n-\t\tgit mailinfo $keep $utf8 \"$dotest/msg\" \"$dotest/patch\" \\\n-\t\t\t<\"$dotest/$msgnum\" >\"$dotest/info\" ||\n-\t\t\tstop_here $this\n+test -n \"$interactive\" && echo 'again' >\"$dotest/interactive\"\n \n-\t\t# skip pine's internal folder data\n-\t\tgrep '^Author: Mail System Internal Data$' \\\n-\t\t\t<\"$dotest\"/info >/dev/null &&\n-\t\t\tgo_next && continue\n+# converting our options to git-sequencer file insn options\n+test -n \"$binary\" && opts=\"$opts --binary\"\n+test -n \"$utf8\" || opts=\"$opts -n\"\n+test -n \"$keep\" && opts=\"$opts -k\"\n+test -n \"$sign\" && opts=\"$opts --signoff\"\n+test -n \"$threeway\" && opts=\"$opts -3\"\n \n-\t\ttest -s $dotest/patch || {\n-\t\t\techo \"Patch is empty.  Was it split wrong?\"\n-\t\t\tstop_here $this\n-\t\t}\n-\t\tif test -f \"$dotest/rebasing\" &&\n-\t\t\tcommit=$(sed -e 's/^From \\([0-9a-f]*\\) .*/\\1/' \\\n-\t\t\t\t-e q \"$dotest/$msgnum\") &&\n-\t\t\ttest \"$(git cat-file -t \"$commit\")\" = commit\n-\t\tthen\n-\t\t\tgit cat-file commit \"$commit\" |\n-\t\t\tsed -e '1,/^$/d' >\"$dotest/msg-clean\"\n-\t\telse\n-\t\t\tSUBJECT=\"$(sed -n '/^Subject/ s/Subject: //p' \"$dotest/info\")\"\n-\t\t\tcase \"$keep_subject\" in -k)  SUBJECT=\"[PATCH] $SUBJECT\" ;; esac\n-\n-\t\t\t(printf '%s\\n\\n' \"$SUBJECT\"; cat \"$dotest/msg\") |\n-\t\t\t\tgit stripspace > \"$dotest/msg-clean\"\n-\t\tfi\n-\t\t;;\n-\tesac\n-\n-\tGIT_AUTHOR_NAME=\"$(sed -n '/^Author/ s/Author: //p' \"$dotest/info\")\"\n-\tGIT_AUTHOR_EMAIL=\"$(sed -n '/^Email/ s/Email: //p' \"$dotest/info\")\"\n-\tGIT_AUTHOR_DATE=\"$(sed -n '/^Date/ s/Date: //p' \"$dotest/info\")\"\n-\n-\tif test -z \"$GIT_AUTHOR_EMAIL\"\n-\tthen\n-\t\techo \"Patch does not have a valid e-mail address.\"\n-\t\tstop_here $this\n-\tfi\n-\n-\texport GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE\n-\n-\tcase \"$resume\" in\n-\t'')\n-\t    if test '' != \"$SIGNOFF\"\n-\t    then\n-\t\tLAST_SIGNED_OFF_BY=`\n-\t\t    sed -ne '/^Signed-off-by: /p' \\\n-\t\t    \"$dotest/msg-clean\" |\n-\t\t    sed -ne '$p'\n-\t\t`\n-\t\tADD_SIGNOFF=`\n-\t\t    test \"$LAST_SIGNED_OFF_BY\" = \"$SIGNOFF\" || {\n-\t\t    test '' = \"$LAST_SIGNED_OFF_BY\" && echo\n-\t\t    echo \"$SIGNOFF\"\n-\t\t}`\n-\t    else\n-\t\tADD_SIGNOFF=\n-\t    fi\n-\t    {\n-\t\tif test -s \"$dotest/msg-clean\"\n-\t\tthen\n-\t\t\tcat \"$dotest/msg-clean\"\n-\t\tfi\n-\t\tif test '' != \"$ADD_SIGNOFF\"\n-\t\tthen\n-\t\t\techo \"$ADD_SIGNOFF\"\n-\t\tfi\n-\t    } >\"$dotest/final-commit\"\n-\t    ;;\n-\t*)\n-\t\tcase \"$resolved$interactive\" in\n-\t\ttt)\n-\t\t\t# This is used only for interactive view option.\n-\t\t\tgit diff-index -p --cached HEAD -- >\"$dotest/patch\"\n-\t\t\t;;\n-\t\tesac\n-\tesac\n-\n-\tresume=\n-\tif test \"$interactive\" = t\n-\tthen\n-\t    test -t 0 ||\n-\t    die \"cannot be interactive without stdin connected to a terminal.\"\n-\t    action=again\n-\t    while test \"$action\" = again\n-\t    do\n-\t\techo \"Commit Body is:\"\n-\t\techo \"--------------------------\"\n-\t\tcat \"$dotest/final-commit\"\n-\t\techo \"--------------------------\"\n-\t\tprintf \"Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all \"\n-\t\tread reply\n-\t\tcase \"$reply\" in\n-\t\t[yY]*) action=yes ;;\n-\t\t[aA]*) action=yes interactive= ;;\n-\t\t[nN]*) action=skip ;;\n-\t\t[eE]*) git_editor \"$dotest/final-commit\"\n-\t\t       action=again ;;\n-\t\t[vV]*) action=again\n-\t\t       LESS=-S ${PAGER:-less} \"$dotest/patch\" ;;\n-\t\t*)     action=again ;;\n-\t\tesac\n-\t    done\n-\telse\n-\t    action=yes\n-\tfi\n-\tFIRSTLINE=$(sed 1q \"$dotest/final-commit\")\n+# create todofile\n+: > \"$todofile\" ||\n+\tdie_abort \"Cannot create $todofile\"\n+while test \"$this\" -le \"$last\"\n+do\n+\tmsgnum=$(printf \"%0${prec}d\" $this)\n+\tthis=$(($this+1))\n \n-\tif test $action = skip\n-\tthen\n-\t\tgo_next\n+\t# This ignores every mail that does not contain a patch.\n+\tgrep '^diff' \"$dotest/$msgnum\" >/dev/null ||\n \t\tcontinue\n-\tfi\n-\n-\tif test -x \"$GIT_DIR\"/hooks/applypatch-msg\n-\tthen\n-\t\t\"$GIT_DIR\"/hooks/applypatch-msg \"$dotest/final-commit\" ||\n-\t\tstop_here $this\n-\tfi\n \n-\tprintf 'Applying %s\\n' \"$FIRSTLINE\"\n-\n-\tcase \"$resolved\" in\n-\t'')\n-\t\tgit apply $git_apply_opt $binary --index \"$dotest/patch\"\n-\t\tapply_status=$?\n-\t\t;;\n-\tt)\n-\t\t# Resolved means the user did all the hard work, and\n-\t\t# we do not have to do any patch application.  Just\n-\t\t# trust what the user has in the index file and the\n-\t\t# working tree.\n-\t\tresolved=\n-\t\tgit diff-index --quiet --cached HEAD -- && {\n-\t\t\techo \"No changes - did you forget to use 'git add'?\"\n-\t\t\tstop_here_user_resolve $this\n-\t\t}\n-\t\tunmerged=$(git ls-files -u)\n-\t\tif test -n \"$unmerged\"\n-\t\tthen\n-\t\t\techo \"You still have unmerged paths in your index\"\n-\t\t\techo \"did you forget to use 'git add'?\"\n-\t\t\tstop_here_user_resolve $this\n-\t\tfi\n-\t\tapply_status=0\n-\t\tgit rerere\n-\t\t;;\n-\tesac\n-\n-\tif test $apply_status = 1 && test \"$threeway\" = t\n-\tthen\n-\t\tif (fall_back_3way)\n-\t\tthen\n-\t\t    # Applying the patch to an earlier tree and merging the\n-\t\t    # result may have produced the same tree as ours.\n-\t\t    git diff-index --quiet --cached HEAD -- && {\n-\t\t\techo No changes -- Patch already applied.\n-\t\t\tgo_next\n-\t\t\tcontinue\n-\t\t    }\n-\t\t    # clear apply_status -- we have successfully merged.\n-\t\t    apply_status=0\n-\t\tfi\n-\tfi\n-\tif test $apply_status != 0\n-\tthen\n-\t\techo Patch failed at $msgnum.\n-\t\tstop_here_user_resolve $this\n-\tfi\n-\n-\tif test -x \"$GIT_DIR\"/hooks/pre-applypatch\n-\tthen\n-\t\t\"$GIT_DIR\"/hooks/pre-applypatch || stop_here $this\n-\tfi\n-\n-\ttree=$(git write-tree) &&\n-\tparent=$(git rev-parse --verify HEAD) &&\n-\tcommit=$(git commit-tree $tree -p $parent <\"$dotest/final-commit\") &&\n-\tgit update-ref -m \"$GIT_REFLOG_ACTION: $FIRSTLINE\" HEAD $commit $parent ||\n-\tstop_here $this\n-\n-\tif test -x \"$GIT_DIR\"/hooks/post-applypatch\n-\tthen\n-\t\t\"$GIT_DIR\"/hooks/post-applypatch\n-\tfi\n-\n-\tgo_next\n+\tprintf 'patch%s \"%s\" #%s\\n' \\\n+\t\t\"$opts\" \"$dotest/$msgnum\" \\\n+\t\t\"$(sed -n '1,/^Subject:/s/Subject://p' \"$dotest/$msgnum\")\" >> \"$todofile\"\n+\ttest -n \"$interactive\" && echo 'pause' >>\"$todofile\"\n done\n \n-git gc --auto\n-\n-rm -fr \"$dotest\"\n+run_sequencer $interactive \"$todofile\"\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex e2d85ee..b0d4c7d 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -216,12 +216,11 @@ do\n \t\tif test -d \"$dotest\"\n \t\tthen\n \t\t\tmove_to_original_branch\n+\t\t\tgit reset --hard $(cat \"$dotest/orig-head\")\n+\t\t\trm -r \"$dotest\"\n \t\telse\n-\t\t\tdotest=.dotest\n-\t\t\tmove_to_original_branch\n+\t\t\tgit am --abort\n \t\tfi\n-\t\tgit reset --hard $(cat \"$dotest/orig-head\")\n-\t\trm -r \"$dotest\"\n \t\texit\n \t\t;;\n \t--onto)\ndiff --git a/t/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh\nindex 1777ffe..f6bbd51 100755\n--- a/t/t3407-rebase-abort.sh\n+++ b/t/t3407-rebase-abort.sh\n@@ -39,9 +39,11 @@ testrebase() {\n \t\tgit reset --hard pre-rebase &&\n \t\ttest_must_fail git rebase$type master &&\n \t\ttest -d \"$dotest\" &&\n+\t\t#test -d \".git/sequencer\" &&\n \t\tgit rebase --abort &&\n \t\ttest $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&\n-\t\ttest ! -d \"$dotest\"\n+\t\ttest ! -d \"$dotest\" &&\n+\t\ttest ! -d \".git/sequencer\"\n \t'\n \n \ttest_expect_success \"rebase$type --abort after --skip\" '\n@@ -54,7 +56,8 @@ testrebase() {\n \t\ttest $(git rev-parse HEAD) = $(git rev-parse master) &&\n \t\tgit-rebase --abort &&\n \t\ttest $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&\n-\t\ttest ! -d \"$dotest\"\n+\t\ttest ! -d \"$dotest\" &&\n+\t\ttest ! -d \".git/sequencer\"\n \t'\n \n \ttest_expect_success \"rebase$type --abort after --continue\" '\n@@ -70,7 +73,8 @@ testrebase() {\n \t\ttest $(git rev-parse HEAD) != $(git rev-parse master) &&\n \t\tgit rebase --abort &&\n \t\ttest $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&\n-\t\ttest ! -d \"$dotest\"\n+\t\ttest ! -d \"$dotest\" &&\n+\t\ttest ! -d \".git/sequencer\"\n \t'\n }\n \ndiff --git a/t/t4150-am.sh b/t/t4150-am.sh\nindex bc98260..a9ee55e 100755\n--- a/t/t4150-am.sh\n+++ b/t/t4150-am.sh\n@@ -83,6 +83,10 @@ test_expect_success setup '\n \tgit commit -m third &&\n \tgit format-patch --stdout first >patch2\t&&\n \tgit checkout -b lorem &&\n+\techo new >another &&\n+\tgit add another &&\n+\ttest_tick &&\n+\tgit commit -m \"added another file\" &&\n \tsed -n -e \"11,\\$p\" msg >file &&\n \thead -n 9 msg >>file &&\n \ttest_tick &&\n@@ -181,7 +185,7 @@ test_expect_success 'am -3 falls back to 3-way merge' '\n '\n \n test_expect_success 'am pauses on conflict' '\n-\tgit checkout lorem2^^ &&\n+\tgit checkout lorem2~3 &&\n \t! git am lorem-move.patch &&\n \ttest -d .dotest\n '\n@@ -193,8 +197,17 @@ test_expect_success 'am --skip works' '\n \ttest goodbye = \"$(cat another)\"\n '\n \n+test_expect_success 'am --abort works' '\n+\tgit checkout lorem2~3 &&\n+\t! git am lorem-move.patch &&\n+\ttest -d .dotest &&\n+\tgit am --abort &&\n+\ttest \"$(git rev-parse HEAD)\" = \"$(git rev-parse lorem2~3)\" &&\n+\t! test -f another\n+'\n+\n test_expect_success 'am --resolved works' '\n-\tgit checkout lorem2^^ &&\n+\tgit checkout lorem2~3 &&\n \t! git am lorem-move.patch &&\n \ttest -d .dotest &&\n \techo resolved >>file &&\n@@ -212,14 +225,12 @@ test_expect_success 'am takes patches from a Pine mailbox' '\n '\n \n test_expect_success 'am fails on mail without patch' '\n-\t! git am <failmail &&\n-\trm -r .dotest/\n+\t! git am <failmail\n '\n \n test_expect_success 'am fails on empty patch' '\n \techo \"---\" >>failmail &&\n \t! git am <failmail &&\n-\tgit am --skip &&\n \t! test -d .dotest\n '\n \n-- \n1.5.6.334.gdaf0\n"},{"id":"81829","messageId":"1214879968-17944-1-git-send-email-s-beyer@gmx.net","threadId":"14239","inReplyTo":"1214879914-17866-5-git-send-email-s-beyer@gmx.net","subject":"git-rebase-i migration to sequencer","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-01T02:39:26Z","receivedAt":"2008-07-01T02:39:26Z","isPatch":false,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nthe patches for rebase-i migration follow.\n\nWhy this intermediate mail?\nBecause the patches will not apply to master/next/pu/whatever.\nIt needs js/rebase-i-sequencer, that is \"dropped for now\" from\ngit.git.  So you have to do some extra work to apply.\n\nWell, I could've just added a \"Squashed js/rebase-i-sequencer patch\"\nor something, but\n 1. I didn't write the patches so I don't want to claim I'm the author,\n 2. It's an opportunity to try sequencer, as follows:\n\nIf you still have the commits (a freshly cloned repo hasn't),\nyou can do:\n\ngit sequencer <<EOF\n#pick 367bcc9cbc3d903c076f # optional: \"fake-editor: output TODO list if unchanged\"\npick 0fa413ebc6e073a52d88\npick -R 88b1f0b8094638b1f953 # just to prevent a silly conflict\npick 966fdf0ab272a64250fb\npick 45d6022d611fd86a13c5\npick 051e0cfb88cd1d2a24bd\n# note: the following patches will make t3404 fail until migration to sequencer\npick d9711a80796fd00169ca\npick 10046a6f8adaccac0ea1\npick abe32eafcd8302c387ed\npick d481bcc93f393bbfaaef\npick dbcd70439f697deeb317\npick b1ba88d812434a51889f\npick cc76fdac36ff25eaa77b\npick f8e037d76a224bd87236\npick 777790a3bdfeb91ee4a6\npick 7cdf70106412f44b9116\npick 14a4f1e0a804ccc905d7\nEOF\n\nIf this results in a lot of \"is not a commit\" errors, then do\n\tgit sequencer --abort\n\t(You may also have a look at git sequencer --status, if you like)\nand fetch the missing commits:\n\tgit fetch git://repo.or.cz/git/sbeyer.git seq-proto-dev2\nand then redo the example above.\n\nWhen the patches are applied, the following patches will apply, too.\n\nRegards,\n  Stephan\n\nPS: Sorry, for the nastiness of the patch application ;-)\n"},{"id":"81828","messageId":"1214879968-17944-2-git-send-email-s-beyer@gmx.net","threadId":"14239","inReplyTo":"1214879968-17944-1-git-send-email-s-beyer@gmx.net","subject":"[PATCH 1/2] Make rebase--interactive use OPTIONS_SPEC","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-01T02:39:27Z","receivedAt":"2008-07-01T02:39:27Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Also add some checks that --continue/--abort/--skip\nactions are used without --onto, -p, -t, etc.\n\nSigned-off-by: Stephan Beyer <s-beyer@gmx.net>\n---\n git-rebase--interactive.sh |   72 ++++++++++++++++++++++++++++---------------\n 1 files changed, 47 insertions(+), 25 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 7e073bb..ad16fa2 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -10,10 +10,27 @@\n # The original idea comes from Eric W. Biederman, in\n # http://article.gmane.org/gmane.comp.version-control.git/22407\n \n-USAGE='(--continue | --abort | --skip | [--preserve-merges] [--first-parent]\n-\t[--preserve-tags] [--verbose] [--onto <branch>] <upstream> [<branch>])'\n+OPTIONS_KEEPDASHDASH=\n+OPTIONS_SPEC=\"\\\n+git-rebase [-i] [options] [--] <upstream> [<branch>]\n+git-rebase [-i] (--continue | --abort | --skip)\n+--\n+ Available options are\n+p,preserve-merges  try to recreate merges instead of ignoring them\n+t,preserve-tags    update tags to the new commit object\n+m,merge            always used (no-op)\n+i,interactive      always used (no-op)\n+onto=              rebase onto given branch instead of upstream\n+v,verbose          display a diffstat of what changed upstream\n+ When preserving merges\n+f,first-parent     show only commits following the first parent of each commit\n+s,strategy=        use the given merge strategy\n+ Actions:\n+continue           continue rebasing process\n+abort              abort rebasing process and restore original branch\n+skip               skip current patch and continue rebasing process\n+\"\n \n-OPTIONS_SPEC=\n . git-sh-setup\n require_work_tree\n \n@@ -25,6 +42,8 @@ SQUASH_MSG=\"$DOTEST\"/message-squash\n PRESERVE_MERGES=\n STRATEGY=\n VERBOSE=\n+ONTO=\n+MARK_PREFIX='refs/rebase-marks'\n test -f \"$DOTEST\"/strategy && STRATEGY=\"$(cat \"$DOTEST\"/strategy)\"\n test -f \"$DOTEST\"/verbose && VERBOSE=t\n \n@@ -515,10 +534,19 @@ create_extended_todo_list () {\n \tdone\n }\n \n+is_standalone () {\n+\ttest $# -eq 2 -a \"$2\" = '--' &&\n+\ttest -z \"$ONTO\" &&\n+\ttest -z \"$PRESERVE_TAGS\" &&\n+\ttest -z \"$PRESERVE_MERGES\" &&\n+\ttest -z \"$FIRST_PARENT\"\n+}\n+\n while test $# != 0\n do\n \tcase \"$1\" in\n \t--continue)\n+\t\tis_standalone \"$@\" || usage\n \t\tcomment_for_reflog continue\n \n \t\ttest -d \"$DOTEST\" || die \"No interactive rebase running\"\n@@ -551,6 +579,7 @@ do\n \t\tdo_rest\n \t\t;;\n \t--abort)\n+\t\tis_standalone \"$@\" || usage\n \t\tcomment_for_reflog abort\n \n \t\tgit rerere clear\n@@ -568,6 +597,7 @@ do\n \t\texit\n \t\t;;\n \t--skip)\n+\t\tis_standalone \"$@\" || usage\n \t\tcomment_for_reflog skip\n \n \t\tgit rerere clear\n@@ -575,7 +605,7 @@ do\n \n \t\toutput git reset --hard && do_rest\n \t\t;;\n-\t-s|--strategy)\n+\t-s)\n \t\tcase \"$#,$1\" in\n \t\t*,*=*)\n \t\t\tSTRATEGY=\"-s \"$(expr \"z$1\" : 'z-[^=]*=\\(.*\\)') ;;\n@@ -586,32 +616,33 @@ do\n \t\t\tshift ;;\n \t\tesac\n \t\t;;\n-\t-m|--merge)\n+\t-m)\n \t\t# we use merge anyway\n \t\t;;\n-\t-C*)\n-\t\tdie \"Interactive rebase uses merge, so $1 does not make sense\"\n-\t\t;;\n-\t-v|--verbose)\n+\t-v)\n \t\tVERBOSE=t\n \t\t;;\n-\t-p|--preserve-merges)\n+\t-p)\n \t\tPRESERVE_MERGES=t\n \t\t;;\n-\t-f|--first-parent)\n+\t-f)\n \t\tFIRST_PARENT=t\n \t\tPRESERVE_MERGES=t\n \t\t;;\n-\t-t|--preserve-tags)\n+\t-t)\n \t\tPRESERVE_TAGS=t\n \t\t;;\n-\t-i|--interactive)\n+\t-i)\n \t\t# yeah, we know\n \t\t;;\n-\t''|-h)\n-\t\tusage\n+\t--onto)\n+\t\tshift\n+\t\tONTO=$(git rev-parse --verify \"$1\") ||\n+\t\t\tdie \"Does not point to a valid commit: $1\"\n \t\t;;\n-\t*)\n+\t--)\n+\t\tshift\n+\t\ttest $# -eq 1 -o $# -eq 2 || usage\n \t\ttest -d \"$DOTEST\" &&\n \t\t\tdie \"Interactive rebase already started\"\n \n@@ -620,15 +651,6 @@ do\n \n \t\tcomment_for_reflog start\n \n-\t\tONTO=\n-\t\tcase \"$1\" in\n-\t\t--onto)\n-\t\t\tONTO=$(git rev-parse --verify \"$2\") ||\n-\t\t\t\tdie \"Does not point to a valid commit: $2\"\n-\t\t\tshift; shift\n-\t\t\t;;\n-\t\tesac\n-\n \t\trequire_clean_work_tree\n \n \t\tUPSTREAM=$(git rev-parse --verify \"$1\") || die \"Invalid base\"\n-- \n1.5.6.334.gdaf0\n"},{"id":"81830","messageId":"1214879968-17944-3-git-send-email-s-beyer@gmx.net","threadId":"14239","inReplyTo":"1214879968-17944-2-git-send-email-s-beyer@gmx.net","subject":"[RFC/PATCH 2/2] Migrate git-rebase--i to use git-sequencer","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-01T02:39:28Z","receivedAt":"2008-07-01T02:39:28Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Signed-off-by: Stephan Beyer <s-beyer@gmx.net>\n---\n git-rebase--interactive.sh    |  423 ++++++-----------------------------------\n t/t3404-rebase-interactive.sh |   29 ++--\n 2 files changed, 71 insertions(+), 381 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex ad16fa2..60f43b2 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -35,28 +35,13 @@ skip               skip current patch and continue rebasing process\n require_work_tree\n \n DOTEST=\"$GIT_DIR/.dotest-merge\"\n-TODO=\"$DOTEST\"/git-rebase-todo\n-DONE=\"$DOTEST\"/done\n-MSG=\"$DOTEST\"/message\n-SQUASH_MSG=\"$DOTEST\"/message-squash\n+TODO=\"$DOTEST/git-rebase-todo\"\n PRESERVE_MERGES=\n STRATEGY=\n VERBOSE=\n+INTERACTIVE=\n ONTO=\n-MARK_PREFIX='refs/rebase-marks'\n-test -f \"$DOTEST\"/strategy && STRATEGY=\"$(cat \"$DOTEST\"/strategy)\"\n-test -f \"$DOTEST\"/verbose && VERBOSE=t\n-\n-GIT_CHERRY_PICK_HELP=\"  After resolving the conflicts,\n-mark the corrected paths with 'git add <paths>', and\n-run 'git rebase --continue'\"\n-export GIT_CHERRY_PICK_HELP\n-\n-mark_prefix=refs/rebase-marks/\n-\n-warn () {\n-\techo \"$*\" >&2\n-}\n+test -f \"$DOTEST\"/verbose && VERBOSE=--verbose\n \n output () {\n \tcase \"$VERBOSE\" in\n@@ -83,51 +68,11 @@ require_clean_work_tree () {\n \n ORIG_REFLOG_ACTION=\"$GIT_REFLOG_ACTION\"\n \n-comment_for_reflog () {\n-\tcase \"$ORIG_REFLOG_ACTION\" in\n-\t''|rebase*)\n-\t\tGIT_REFLOG_ACTION=\"rebase -i ($1)\"\n-\t\texport GIT_REFLOG_ACTION\n-\t\t;;\n-\tesac\n-}\n-\n-last_count=\n-mark_action_done () {\n-\tsed -e 1q < \"$TODO\" >> \"$DONE\"\n-\tsed -e 1d < \"$TODO\" >> \"$TODO\".new\n-\tmv -f \"$TODO\".new \"$TODO\"\n-\tcount=$(grep -c '^[^#]' < \"$DONE\")\n-\ttotal=$(($count+$(grep -c '^[^#]' < \"$TODO\")))\n-\tif test \"$last_count\" != \"$count\"\n-\tthen\n-\t\tlast_count=$count\n-\t\tprintf \"Rebasing (%d/%d)\\r\" $count $total\n-\t\ttest -z \"$VERBOSE\" || echo\n-\tfi\n-}\n-\n-make_patch () {\n-\tparent_sha1=$(git rev-parse --verify \"$1\"^) ||\n-\t\tdie \"Cannot get patch for $1^\"\n-\tgit diff-tree -p \"$parent_sha1\"..\"$1\" > \"$DOTEST\"/patch\n-\ttest -f \"$DOTEST\"/message ||\n-\t\tgit cat-file commit \"$1\" | sed \"1,/^$/d\" > \"$DOTEST\"/message\n-\ttest -f \"$DOTEST\"/author-script ||\n-\t\tget_author_ident_from_commit \"$1\" > \"$DOTEST\"/author-script\n-}\n-\n-die_with_patch () {\n-\tmake_patch \"$1\"\n-\tgit rerere\n-\tdie \"$2\"\n+warn () {\n+\techo \"$*\" >&2\n }\n \n cleanup_before_quit () {\n-\tfor ref in $(git for-each-ref --format='%(refname)' \"${mark_prefix%/}\")\n-\tdo\n-\t\tgit update-ref -d \"$ref\" \"$ref\" || return 1\n-\tdone\n \trm -rf \"$DOTEST\"\n }\n \n@@ -136,229 +81,13 @@ die_abort () {\n \tdie \"$1\"\n }\n \n-has_action () {\n-\tgrep '^[^#]' \"$1\" >/dev/null\n-}\n-\n-redo_merge () {\n-\trm_sha1=$1\n-\tshift\n-\n-\teval \"$(get_author_ident_from_commit $rm_sha1)\"\n-\tmsg=\"$(git cat-file commit $rm_sha1 | sed -e '1,/^$/d')\"\n-\n-\tif ! GIT_AUTHOR_NAME=\"$GIT_AUTHOR_NAME\" \\\n-\t\tGIT_AUTHOR_EMAIL=\"$GIT_AUTHOR_EMAIL\" \\\n-\t\tGIT_AUTHOR_DATE=\"$GIT_AUTHOR_DATE\" \\\n-\t\toutput git merge $STRATEGY -m \"$msg\" \"$@\"\n-\tthen\n-\t\tgit rerere\n-\t\tprintf \"%s\\n\" \"$msg\" > \"$GIT_DIR\"/MERGE_MSG\n-\t\tdie Error redoing merge $rm_sha1\n-\tfi\n-\tunset rm_sha1\n-}\n-\n-pick_one () {\n-\tno_ff=\n-\tcase \"$1\" in -n) sha1=$2; no_ff=t ;; *) sha1=$1 ;; esac\n-\toutput git rev-parse --verify $sha1 || die \"Invalid commit name: $sha1\"\n-\tparent_sha1=$(git rev-parse --verify $sha1^) ||\n-\t\tdie \"Could not get the parent of $sha1\"\n-\tcurrent_sha1=$(git rev-parse --verify HEAD)\n-\tif test \"$no_ff$current_sha1\" = \"$parent_sha1\"; then\n-\t\toutput git reset --hard $sha1\n-\t\ttest \"a$1\" = a-n && output git reset --soft $current_sha1\n-\t\tsha1=$(git rev-parse --short $sha1)\n-\t\toutput warn Fast forward to $sha1\n-\telse\n-\t\toutput git cherry-pick \"$@\"\n-\tfi\n-}\n-\n-nth_string () {\n-\tcase \"$1\" in\n-\t*1[0-9]|*[04-9]) echo \"$1\"th;;\n-\t*1) echo \"$1\"st;;\n-\t*2) echo \"$1\"nd;;\n-\t*3) echo \"$1\"rd;;\n-\tesac\n-}\n-\n-make_squash_message () {\n-\tif test -f \"$SQUASH_MSG\"; then\n-\t\tCOUNT=$(($(sed -n \"s/^# This is [^0-9]*\\([1-9][0-9]*\\).*/\\1/p\" \\\n-\t\t\t< \"$SQUASH_MSG\" | sed -ne '$p')+1))\n-\t\techo \"# This is a combination of $COUNT commits.\"\n-\t\tsed -e 1d -e '2,/^./{\n-\t\t\t/^$/d\n-\t\t}' <\"$SQUASH_MSG\"\n-\telse\n-\t\tCOUNT=2\n-\t\techo \"# This is a combination of two commits.\"\n-\t\techo \"# The first commit's message is:\"\n-\t\techo\n-\t\tgit cat-file commit HEAD | sed -e '1,/^$/d'\n-\tfi\n-\techo\n-\techo \"# This is the $(nth_string $COUNT) commit message:\"\n-\techo\n-\tgit cat-file commit $1 | sed -e '1,/^$/d'\n-}\n-\n-peek_next_command () {\n-\tsed -n \"1s/ .*$//p\" < \"$TODO\"\n-}\n-\n-mark_to_ref () {\n-\tif expr \"$1\" : \"^:[0-9][0-9]*$\" >/dev/null\n-\tthen\n-\t\techo \"$mark_prefix$(printf %d ${1#:})\"\n-\telse\n-\t\techo \"$1\"\n-\tfi\n-}\n-\n-do_next () {\n-\trm -f \"$DOTEST\"/message \"$DOTEST\"/author-script \\\n-\t\t\"$DOTEST\"/amend || exit\n-\tread command sha1 rest < \"$TODO\"\n-\tcase \"$command\" in\n-\t'#'*|'')\n-\t\tmark_action_done\n-\t\t;;\n-\tpick|p)\n-\t\tcomment_for_reflog pick\n-\n-\t\tmark_action_done\n-\t\tpick_one $sha1 ||\n-\t\t\tdie_with_patch $sha1 \"Could not apply $sha1... $rest\"\n-\t\t;;\n-\tedit|e)\n-\t\tcomment_for_reflog edit\n-\n-\t\tmark_action_done\n-\t\tpick_one $sha1 ||\n-\t\t\tdie_with_patch $sha1 \"Could not apply $sha1... $rest\"\n-\t\tmake_patch $sha1\n-\t\t: > \"$DOTEST\"/amend\n-\t\twarn\n-\t\twarn \"You can amend the commit now, with\"\n-\t\twarn\n-\t\twarn \"\tgit commit --amend\"\n-\t\twarn\n-\t\twarn \"Once you are satisfied with your changes, run\"\n-\t\twarn\n-\t\twarn \"\tgit rebase --continue\"\n-\t\twarn\n-\t\texit 0\n-\t\t;;\n-\tsquash|s)\n-\t\tcomment_for_reflog squash\n-\n-\t\thas_action \"$DONE\" ||\n-\t\t\tdie \"Cannot 'squash' without a previous commit\"\n-\n-\t\tmark_action_done\n-\t\tmake_squash_message $sha1 > \"$MSG\"\n-\t\tcase \"$(peek_next_command)\" in\n-\t\tsquash|s)\n-\t\t\tEDIT_COMMIT=\n-\t\t\tUSE_OUTPUT=output\n-\t\t\tcp \"$MSG\" \"$SQUASH_MSG\"\n-\t\t\t;;\n-\t\t*)\n-\t\t\tEDIT_COMMIT=-e\n-\t\t\tUSE_OUTPUT=\n-\t\t\trm -f \"$SQUASH_MSG\" || exit\n-\t\t\t;;\n-\t\tesac\n-\n-\t\tfailed=f\n-\t\tauthor_script=$(get_author_ident_from_commit HEAD)\n-\t\toutput git reset --soft HEAD^\n-\t\tpick_one -n $sha1 || failed=t\n-\t\techo \"$author_script\" > \"$DOTEST\"/author-script\n-\t\tif test $failed = f\n-\t\tthen\n-\t\t\t# This is like --amend, but with a different message\n-\t\t\teval \"$author_script\"\n-\t\t\tGIT_AUTHOR_NAME=\"$GIT_AUTHOR_NAME\" \\\n-\t\t\tGIT_AUTHOR_EMAIL=\"$GIT_AUTHOR_EMAIL\" \\\n-\t\t\tGIT_AUTHOR_DATE=\"$GIT_AUTHOR_DATE\" \\\n-\t\t\t$USE_OUTPUT git commit --no-verify -F \"$MSG\" $EDIT_COMMIT || failed=t\n-\t\tfi\n-\t\tif test $failed = t\n-\t\tthen\n-\t\t\tcp \"$MSG\" \"$GIT_DIR\"/MERGE_MSG\n-\t\t\twarn\n-\t\t\twarn \"Could not apply $sha1... $rest\"\n-\t\t\tdie_with_patch $sha1 \"\"\n-\t\tfi\n-\t\t;;\n-\tmark)\n-\t\tmark_action_done\n-\n-\t\tmark=$(mark_to_ref :${sha1#:})\n-\t\ttest :${sha1#:} = \"$mark\" && die \"Invalid mark '$sha1'\"\n-\n-\t\tgit rev-parse --verify \"$mark\" > /dev/null 2>&1 && \\\n-\t\t\twarn \"mark $sha1 already exist; overwriting it\"\n-\n-\t\tgit update-ref \"$mark\" HEAD || die \"update-ref failed\"\n-\t\t;;\n-\tmerge|m)\n-\t\tcomment_for_reflog merge\n-\n-\t\tif ! git rev-parse --verify $sha1 > /dev/null\n-\t\tthen\n-\t\t\tdie \"Invalid reference merge '$sha1' in\"\n-\t\t\t\t\t\"$command $sha1 $rest\"\n-\t\tfi\n-\n-\t\tnew_parents=\n-\t\tfor p in $rest\n-\t\tdo\n-\t\t\tnew_parents=\"$new_parents $(mark_to_ref $p)\"\n-\t\tdone\n-\t\tnew_parents=\"${new_parents# }\"\n-\t\ttest -n \"$new_parents\" || \\\n-\t\t\tdie \"You forgot to give the parents for the\" \\\n-\t\t\t\t\"merge $sha1. Please fix it in $TODO\"\n-\n-\t\tmark_action_done\n-\t\tredo_merge $sha1 $new_parents\n-\t\t;;\n-\treset|r)\n-\t\tcomment_for_reflog reset\n-\n-\t\ttmp=$(git rev-parse --verify \"$(mark_to_ref $sha1)\") ||\n-\t\t\tdie \"Invalid parent '$sha1' in $command $sha1 $rest\"\n-\n-\t\tmark_action_done\n-\t\toutput git reset --hard $tmp\n-\t\t;;\n-\ttag|t)\n-\t\tcomment_for_reflog tag\n-\n-\t\tmark_action_done\n-\t\toutput git tag -f \"$sha1\"\n-\t\t;;\n-\t*)\n-\t\twarn \"Unknown command: $command $sha1 $rest\"\n-\t\tdie_with_patch $sha1 \"Please fix this in the file $TODO.\"\n-\t\t;;\n-\tesac\n-\ttest -s \"$TODO\" && return\n-\n-\tcomment_for_reflog finish &&\n+update_refs () {\n \tHEADNAME=$(cat \"$DOTEST\"/head-name) &&\n \tOLDHEAD=$(cat \"$DOTEST\"/head) &&\n-\tSHORTONTO=$(git rev-parse --short $(cat \"$DOTEST\"/onto)) &&\n \tNEWHEAD=$(git rev-parse HEAD) &&\n \tcase $HEADNAME in\n \trefs/*)\n-\t\tmessage=\"$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO)\" &&\n+\t\tmessage=\"$GIT_REFLOG_ACTION: $HEADNAME)\" &&\n \t\tgit update-ref -m \"$message\" $HEADNAME $NEWHEAD $OLDHEAD &&\n \t\tgit symbolic-ref HEAD $HEADNAME\n \t\t;;\n@@ -369,15 +98,30 @@ do_next () {\n \tcleanup_before_quit &&\n \tgit gc --auto &&\n \twarn \"Successfully rebased and updated $HEADNAME.\"\n+}\n \n-\texit\n+run_sequencer () {\n+\tgit sequencer --caller='git rebase -i|--abort|--continue|--skip' \"$@\"\n+\tcase \"$?\" in\n+\t0)\n+\t\tupdate_refs\n+\t\texit 0\n+\t\t;;\n+\t2)\n+\t\twarn 'git-sequencer needs continuation (by edit).'\n+\t\texit 0\n+\t\t;;\n+\t3)\n+\t\tdie 'git-sequencer needs continuation (by conflict).'\n+\t\t;;\n+\t*)\n+\t\tdie_abort 'git-sequencer died.'\n+\t\t;;\n+\tesac\n }\n \n-do_rest () {\n-\twhile :\n-\tdo\n-\t\tdo_next\n-\tdone\n+has_action () {\n+\tgrep '^[^#]' \"$1\" >/dev/null\n }\n \n get_value_from_list () {\n@@ -418,7 +162,6 @@ create_extended_todo_list () {\n \t\t\t(\n \t\t\twhile read sha1 tag\n \t\t\tdo\n-\t\t\t\ttag=${tag#refs/tags/}\n \t\t\t\tif test ${last_sha1:-0000} = $sha1\n \t\t\t\tthen\n \t\t\t\t\tsaved_tags=\"$saved_tags:$tag\"\n@@ -457,7 +200,7 @@ create_extended_todo_list () {\n \t\tthen\n \t\t\tfor t in $(echo $tmp | tr : ' ')\n \t\t\tdo\n-\t\t\t\techo tag $t\n+\t\t\t\techo ref $t\n \t\t\tdone\n \t\tfi\n \n@@ -477,18 +220,18 @@ create_extended_todo_list () {\n \t\t\t\tfi\n \t\t\tdone\n \t\t\tunset p\n-\t\t\techo merge $commit $new_parents\n+\t\t\techo \"merge $STRATEGY --reuse-commit=$commit $new_parents\"\n \t\t\tunset new_parents\n \t\t\t;;\n \t\t*)\n-\t\t\techo \"pick $commit $subject\"\n+\t\t\techo \"pick $commit # $subject\"\n \t\t\t;;\n \t\tesac\n \tdone\n \ttest -n \"${last_parent:-}\" -a \"${last_parent:-}\" != $SHORTUPSTREAM && \\\n-\t\techo reset $last_parent\n+\t\techo \"reset $last_parent\"\n \t) | \\\n-\tperl -e 'print reverse <>' | \\\n+\t@@PERL@@ -e 'print reverse <>' | \\\n \twhile read cmd args\n \tdo\n \t\t: ${commit_mark_list:=} ${last_commit:=000}\n@@ -515,6 +258,7 @@ create_extended_todo_list () {\n \t\t\tfi\n \t\t\t;;\n \t\tmerge)\n+\t\t\targs=\"${args#*--reuse-commit=}\"\n \t\t\tnew_args=\n \t\t\tfor i in ${args#* }\n \t\t\tdo\n@@ -527,7 +271,7 @@ create_extended_todo_list () {\n \t\t\t\tfi\n \t\t\tdone\n \t\t\tlast_commit=\"${args%% *}\"\n-\t\t\targs=\"$last_commit ${new_args# }\"\n+\t\t\targs=\"$STRATEGY --reuse-commit=$last_commit ${new_args# }\"\n \t\t\t;;\n \t\tesac\n \t\techo \"$cmd $args\"\n@@ -545,65 +289,9 @@ is_standalone () {\n while test $# != 0\n do\n \tcase \"$1\" in\n-\t--continue)\n-\t\tis_standalone \"$@\" || usage\n-\t\tcomment_for_reflog continue\n-\n-\t\ttest -d \"$DOTEST\" || die \"No interactive rebase running\"\n-\n-\t\t# Sanity check\n-\t\tgit rev-parse --verify HEAD >/dev/null ||\n-\t\t\tdie \"Cannot read HEAD\"\n-\t\tgit update-index --ignore-submodules --refresh &&\n-\t\t\tgit diff-files --quiet --ignore-submodules ||\n-\t\t\tdie \"Working tree is dirty\"\n-\n-\t\t# do we have anything to commit?\n-\t\tif git diff-index --cached --quiet --ignore-submodules HEAD --\n-\t\tthen\n-\t\t\t: Nothing to commit -- skip this\n-\t\telse\n-\t\t\t. \"$DOTEST\"/author-script ||\n-\t\t\t\tdie \"Cannot find the author identity\"\n-\t\t\tif test -f \"$DOTEST\"/amend\n-\t\t\tthen\n-\t\t\t\tgit reset --soft HEAD^ ||\n-\t\t\t\tdie \"Cannot rewind the HEAD\"\n-\t\t\tfi\n-\t\t\texport GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE &&\n-\t\t\tgit commit --no-verify -F \"$DOTEST\"/message -e ||\n-\t\t\tdie \"Could not commit staged changes.\"\n-\t\tfi\n-\n-\t\trequire_clean_work_tree\n-\t\tdo_rest\n-\t\t;;\n-\t--abort)\n+\t--continue|--abort|--skip)\n \t\tis_standalone \"$@\" || usage\n-\t\tcomment_for_reflog abort\n-\n-\t\tgit rerere clear\n-\t\ttest -d \"$DOTEST\" || die \"No interactive rebase running\"\n-\n-\t\tHEADNAME=$(cat \"$DOTEST\"/head-name)\n-\t\tHEAD=$(cat \"$DOTEST\"/head)\n-\t\tcase $HEADNAME in\n-\t\trefs/*)\n-\t\t\tgit symbolic-ref HEAD $HEADNAME\n-\t\t\t;;\n-\t\tesac &&\n-\t\toutput git reset --hard $HEAD &&\n-\t\tcleanup_before_quit\n-\t\texit\n-\t\t;;\n-\t--skip)\n-\t\tis_standalone \"$@\" || usage\n-\t\tcomment_for_reflog skip\n-\n-\t\tgit rerere clear\n-\t\ttest -d \"$DOTEST\" || die \"No interactive rebase running\"\n-\n-\t\toutput git reset --hard && do_rest\n+\t\trun_sequencer \"$1\"\n \t\t;;\n \t-s)\n \t\tcase \"$#,$1\" in\n@@ -620,7 +308,7 @@ do\n \t\t# we use merge anyway\n \t\t;;\n \t-v)\n-\t\tVERBOSE=t\n+\t\tVERBOSE=--verbose\n \t\t;;\n \t-p)\n \t\tPRESERVE_MERGES=t\n@@ -633,7 +321,7 @@ do\n \t\tPRESERVE_TAGS=t\n \t\t;;\n \t-i)\n-\t\t# yeah, we know\n+\t\tINTERACTIVE=t\n \t\t;;\n \t--onto)\n \t\tshift\n@@ -649,14 +337,12 @@ do\n \t\tgit var GIT_COMMITTER_IDENT >/dev/null ||\n \t\t\tdie \"You need to set your committer info first\"\n \n-\t\tcomment_for_reflog start\n-\n \t\trequire_clean_work_tree\n \n \t\tUPSTREAM=$(git rev-parse --verify \"$1\") || die \"Invalid base\"\n \t\ttest -z \"$ONTO\" && ONTO=$UPSTREAM\n \n-\t\tif test ! -z \"$2\"\n+\t\tif test -n \"$2\"\n \t\tthen\n \t\t\toutput git show-ref --verify --quiet \"refs/heads/$2\" ||\n \t\t\t\tdie \"Invalid branchname: $2\"\n@@ -674,8 +360,7 @@ do\n \t\techo $HEAD > \"$DOTEST\"/head\n \t\techo $UPSTREAM > \"$DOTEST\"/upstream\n \t\techo $ONTO > \"$DOTEST\"/onto\n-\t\ttest -z \"$STRATEGY\" || echo \"$STRATEGY\" > \"$DOTEST\"/strategy\n-\t\ttest t = \"$VERBOSE\" && : > \"$DOTEST\"/verbose\n+\t\ttest -n \"$VERBOSE\" && : > \"$DOTEST\"/verbose\n \n \t\tSHORTUPSTREAM=$(git rev-parse --short=7 $UPSTREAM)\n \t\tSHORTHEAD=$(git rev-parse --short=7 $HEAD)\n@@ -696,7 +381,8 @@ do\n \t\t\t\tcreate_extended_todo_list\n \t\telse\n \t\t\tgit rev-list --no-merges --reverse --pretty=oneline \\\n-\t\t\t\t $common_rev_list_opts | sed -n \"s/^>/pick /p\"\n+\t\t\t\t $common_rev_list_opts |\n+\t\t\t\t sed -n -e \"s/^>\\([0-9a-f]\\+\\)/pick \\1\\t#/p\"\n \t\tfi > \"$TODO\"\n \n \t\tcat >> \"$TODO\" << EOF\n@@ -713,26 +399,29 @@ do\n #  squash = use commit, but meld into previous commit\n #  mark :mark = mark the current HEAD for later reference\n #  reset commit = reset HEAD to the commit\n-#  merge commit-M commit-P ... = redo merge commit-M with the\n-#         current HEAD and the parents commit-P\n-#  tag = reset tag to the current HEAD\n+#  merge [--reuse-commit=commit-M] remote ... =\n+#     * merge the remotes into HEAD\n+#     * can use the author and commit message from commit-M\n+#  ref = update ref to the current HEAD\n #\n # If you remove a line here THAT COMMIT WILL BE LOST.\n # However, if you remove everything, the rebase will be aborted.\n #\n EOF\n-\n \t\thas_action \"$TODO\" ||\n \t\t\tdie_abort \"Nothing to do\"\n \n-\t\tcp \"$TODO\" \"$TODO\".backup\n-\t\tgit_editor \"$TODO\" ||\n-\t\t\tdie \"Could not execute editor\"\n+\t\tif test -n \"$INTERACTIVE\"\n+\t\tthen\n+\t\t\tcp \"$TODO\" \"$TODO\".backup\n+\t\t\tgit_editor \"$TODO\" ||\n+\t\t\t\tdie_abort \"Could not execute editor\"\n \n-\t\thas_action \"$TODO\" ||\n-\t\t\tdie_abort \"Nothing to do\"\n+\t\t\thas_action \"$TODO\" ||\n+\t\t\t\tdie_abort \"Nothing to do\"\n+\t\tfi\n \n-\t\toutput git checkout $ONTO && do_rest\n+\t\trun_sequencer $VERBOSE --onto \"$ONTO\" \"$TODO\"\n \t\t;;\n \tesac\n \tshift\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 940eb24..8b0781d 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -89,11 +89,11 @@ for line in $FAKE_LINES; do\n \t\techo \"reset ${line#reset}\"\n \t\techo \"reset ${line#reset}\" >> \"$1\";;\n \tmerge*)\n-\t\techo \"merge ${line#merge}\" | tr / ' '\n-\t\techo \"merge ${line#merge}\" | tr / ' ' >> \"$1\";;\n+\t\techo \"merge --reuse-commit=${line#merge}\" | tr / ' '\n+\t\techo \"merge --reuse-commit=${line#merge}\" | tr / ' ' >> \"$1\";;\n \ttag*)\n-\t\techo \"tag ${line#tag}\"\n-\t\techo \"tag ${line#tag}\" >> \"$1\";;\n+\t\techo \"ref refs/tags/${line#tag}\"\n+\t\techo \"ref refs/tags/${line#tag}\" >> \"$1\";;\n \t*)\n \t\tsed -n \"${line}{s/^pick/$action/; p;}\" < \"$1\".tmp\n \t\tsed -n \"${line}{s/^pick/$action/; p;}\" < \"$1\".tmp >> \"$1\"\n@@ -170,19 +170,20 @@ test_expect_success 'stop on conflicting pick' '\n \tgit tag new-branch1 &&\n \ttest_must_fail git rebase -i master &&\n \ttest \"$(git rev-parse HEAD~3)\" = \"$(git rev-parse master)\" &&\n-\ttest_cmp expect .git/.dotest-merge/patch &&\n+\ttest_cmp expect .git/sequencer/patch &&\n \ttest_cmp expect2 file1 &&\n \ttest \"$(git-diff --name-status |\n \t\tsed -n -e \"/^U/s/^U[^a-z]*//p\")\" = file1 &&\n-\ttest 4 = $(grep -v \"^#\" < .git/.dotest-merge/done | wc -l) &&\n-\ttest 0 = $(grep -c \"^[^#]\" < .git/.dotest-merge/git-rebase-todo)\n+\ttest 4 = $(grep -v \"^#\" < .git/sequencer/done | wc -l) &&\n+\ttest 0 = $(grep -c \"^[^#]\" < .git/sequencer/todo) &&\n+\ttest -d .git/.dotest-merge\n '\n \n test_expect_success 'abort' '\n \tgit rebase --abort &&\n \ttest $(git rev-parse new-branch1) = $(git rev-parse HEAD) &&\n \ttest \"$(git symbolic-ref -q HEAD)\" = \"refs/heads/branch1\" &&\n-\t! test -d .git/.dotest-merge\n+\t! test -d .git/sequencer\n '\n \n test_expect_success 'retain authorship' '\n@@ -219,13 +220,13 @@ test_expect_success '-p handles \"no changes\" gracefully' '\n test_expect_success 'setting marks works' '\n \tgit checkout master &&\n \tFAKE_LINES=\"mark:0 2 1 mark:42 3 edit 4\" git rebase -i HEAD~4 &&\n-\tmarks_dir=.git/refs/rebase-marks &&\n+\tmarks_dir=.git/refs/sequencer-marks &&\n \ttest -d $marks_dir &&\n \ttest $(ls $marks_dir | wc -l) -eq 2 &&\n \ttest \"$(git rev-parse HEAD~4)\" = \\\n-\t\t\"$(git rev-parse refs/rebase-marks/0)\" &&\n+\t\t\"$(git rev-parse refs/sequencer-marks/0)\" &&\n \ttest \"$(git rev-parse HEAD~2)\" = \\\n-\t\t\"$(git rev-parse refs/rebase-marks/42)\" &&\n+\t\t\"$(git rev-parse refs/sequencer-marks/42)\" &&\n \tgit rebase --abort &&\n \ttest 0 = $(ls $marks_dir | wc -l)\n '\n@@ -233,8 +234,8 @@ test_expect_success 'setting marks works' '\n test_expect_success 'reset with nonexistent mark fails' '\n \texport FAKE_LINES=\"reset:0 1\" &&\n \ttest_must_fail git rebase -i HEAD~1 &&\n-\tunset FAKE_LINES &&\n-\tgit rebase --abort\n+\tgit rebase --abort &&\n+\tunset FAKE_LINES\n '\n \n test_expect_success 'reset to HEAD is a nop' '\n@@ -325,7 +326,7 @@ test_expect_success 'interactive --first-parent gives a linear list' '\n \ttest \"$head\" = \"$(git rev-parse HEAD)\"\n '\n \n-test_expect_success 'tag sets tags' '\n+test_expect_success 'ref can set tags' '\n \thead=$(git rev-parse HEAD) &&\n \tFAKE_LINES=\"1 2 3 4 5 tagbb-tag1 6 7 8 9 10 11 12 13 14 15 \\\n \t\ttagbb-tag2 16 tagbb-tag3a tagbb-tag3b 17 18 19 20 21 22\" \\\n-- \n1.5.6.334.gdaf0\n"},{"id":"81847","messageId":"7vabh2oulb.fsf@gitster.siamese.dyndns.org","threadId":"14239","inReplyTo":"1214879914-17866-1-git-send-email-s-beyer@gmx.net","subject":"Re: git sequencer prototype","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-01T08:51:44Z","receivedAt":"2008-07-01T08:51:44Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephan Beyer <s-beyer@gmx.net> writes:\n\n> I'm using sequencer-based git-am and git-rebase-i and also git-sequencer\n> itself for around 2-3 weeks now. So, for me, it is reality-proven, but\n> I'm curious about your opinions/suggestions in usage and source.\n\nThanks.\n\n> The migration patches are a little hard to code-review in the diff-form,\n> but feel free to apply, test, and then look at the code ;)\n\nHeh, these three typically come in different order.  Look at the log\nmessage and docs to see if the design is sound, then look at the code, and\nif things overall look Ok, then finally apply and test.\n\nI unfortunately ran out of time tonight and will look at them probably\nThursday evening.  It seems that another GSoC topic is finally nearing\ncompletion and I can shift my attention to other topics now.\n\nBy the way Christian is not CC'ed?\n"},{"id":"81873","messageId":"m34p79hhy9.fsf@localhost.localdomain","threadId":"14239","inReplyTo":"1214879914-17866-3-git-send-email-s-beyer@gmx.net","subject":"Re: [RFC/PATCH 2/4] Add git-sequencer prototype documentation","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-07-01T13:02:54Z","receivedAt":"2008-07-01T13:02:54Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Stephan Beyer <s-beyer@gmx.net> writes:\n\n> Mentored-by: Christian Couder <chriscool@tuxfamily.org>\n> Mentored-by: Daniel Barkalow <barkalow@iabervon.org>\n\nCc mentors?\n\n> +git-sequencer will usually be called by another git porcelain, like\n> +linkgit:git-am[1] or linkgit:git-rebase[1].\n\nI hope that it could be also used by git-cherry-pick and git-revert,\nso it would be possible to pick more than one commit...\n\n> +In case of a conflict or request in the TODO file, git-sequencer will\n> +pause. On conflict you can use git-diff to locate the markers (`<<<<<<<`)\n> +and make edits to resolve the conflict.\n> +\n> +For each file you edit, you need to tell git the changes by doing\n> +\n> +    git add <file>\n> +\n> +After resolving the conflict manually and updating the index with the\n> +desired resolution, you can continue the sequencing process with\n> +\n> +    git sequencer --continue\n\nDoes it run pre-commit hooks, for example checking for merge markers\n(but also whitespace errors), and can those checks be disabled?\n\n> +-B::\n> +--batch::\n> +\tRun in batch mode. If unexpected user intervention is needed\n> +\t(e.g. a conflict or the need to run an editor), git-sequencer fails.\n> ++\n> +Note that the sanity check fails, if you use this option\n> +and an instruction like `edit` or `pause`.\n\ns/.$/ is in the TODO file./\n\n> +--edit::\n> +\tInvoke editor to edit the undone rest of the TODO file.\n\nDoes it mean that editor will be invoked with only _unprocessed_\npart of the TODO file?  It looks like it, but it might be not\nobvious to some.\n\n> +merge [options] <commit-ish1> <commit-ish2> ... <commit-ishN>::\n> +\tMerge commits into HEAD.\n\nNice.\n\n\"HEAD\" mean last picked up / created commit, isn't it?\n\n> ++\n> +A commit can also be given by a mark, if prefixed with a colon.\n\n\"You can refer to commit by mark\", perhaps?\n\n> +\t--standard;;\n> +\t\tGenerates a commit message like 'Merge ... into HEAD'.\n> +\t\tSee also linkgit:git-fmt-merge-msg[1].\n\nIs it short for `--standard-message`?\n\n> +pick [options] <commit>::\n> +\tPick (see linkgit:git-cherry-pick[1]) a commit.\n> +\tSequencer will pause on conflicts.\n> ++\n> +See the following list and 'GENERAL OPTIONS' for values of `options`:\n> +\n> +\t-R;;\n> +\t--reverse;;\n> +\t\tRevert the changes introduced by pick <commit>.\n> +\n> +\t--mainline=<n>;;\n> +\t\tAllows you to pick merge commits by specifying the\n> +\t\tparent number (beginning from 1) to let sequencer\n> +\t\treplay the changes relative to the specified parent.\n> +\t\t+\n> +This option does not work together with `-R`.\n\nWhy?  I would have thought that it would work...\n\n> +patch [options] <file>::\n[...]\n> +\t-*;;\n> +\t\tAny other dash-prefixed option is passed to\n> +\t\tlinkgit:git-apply[1].\n> +\t\tThis is especially useful for flags like\n> +\t\t`--reverse`, `-C<n>`, `-p<n>` or `--whitespace=<action>`.\n\nDo all options make sense?  What about `--index' and `--cached',\nor about different no-apply options?\n\n> +ref <ref>::\n> +\tSet ref `<ref>` to the current HEAD, see also\n> +\tlinkgit:git-update-ref[1].\n\nSo this functions like \"git reset --soft <ref>\", isn't it?\n\n> +squash [options] --from <mark>::\n> +\tSquash all commits from the given mark into one commit.\n> +\tThere must not be any `merge` instructions between the\n> +\t`mark` instruction and this `squash --from` instruction.\n\nCan you use <commit> instead of <mark> here?\n\n> +\t--include-merges;;\n> +\t\tSanity check does not fail if you have merges\n> +\t\tbetween HEAD and <mark>.\n\nHow do you squash merges?  Creating merge with an union of parents,\nexcluding commits which got squashed?\n\nIt means\n\n  ...a---b---c---d         ...[abcd]\n            /        ==>        /\n      ...x-/               ..x-/\n\nbut\n\n  ...a---b---c---d          ...[abcd]\n      \\     /        ==>\n       \\-x-/ \n\n> +RETURN VALUES\n> +-------------\n> +* any other value on error, e.g.\n> +  running git-sequencer on a bare repository.\n\nDon't you enumerate those return values?\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"81878","messageId":"20080701145344.GB5301@leksak.fem-net","threadId":"14239","inReplyTo":"7vabh2oulb.fsf@gitster.siamese.dyndns.org","subject":"Re: git sequencer prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-01T14:53:44Z","receivedAt":"2008-07-01T14:53:44Z","isPatch":false,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\n> > The migration patches are a little hard to code-review in the diff-form,\n> > but feel free to apply, test, and then look at the code ;)\n> \n> Heh, these three typically come in different order.  Look at the log\n> message and docs to see if the design is sound, then look at the code, and\n> if things overall look Ok, then finally apply and test.\n\nHmm, I usually prefer testing first (on such large patches), because I think\nI value things different after I've tested them.\n\n> I unfortunately ran out of time tonight and will look at them probably\n> Thursday evening.\n\nDon't hurry.\n\n> It seems that another GSoC topic is finally nearing\n> completion and I can shift my attention to other topics now.\n\nYes, the builtin merge should perhaps get some more priority first.\n\n> By the way Christian is not CC'ed?\n\nShame on me, I forgot to Cc my mentors ;-)\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"81883","messageId":"20080701160322.GC5301@leksak.fem-net","threadId":"14239","inReplyTo":"m34p79hhy9.fsf@localhost.localdomain","subject":"Re: [RFC/PATCH 2/4] Add git-sequencer prototype documentation","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-01T16:03:22Z","receivedAt":"2008-07-01T16:03:22Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn Tue, Jul 01, 2008 at 06:02:54AM -0700,\nJakub Narebski <jnareb@gmail.com> wrote:\n> > +git-sequencer will usually be called by another git porcelain, like\n> > +linkgit:git-am[1] or linkgit:git-rebase[1].\n> \n> I hope that it could be also used by git-cherry-pick and git-revert,\n> so it would be possible to pick more than one commit...\n\nRight, you've already mentioned it several times. ;-)\nBut I haven't included it currently, because git-sequencer currently *uses*\ncherry-pick/revert to pick/revert commits, and I think this can lead to\nsome confusion.\nAnd, I think there also has to be some discussion, e.g.\nif even the single cherry-pick/revert uses sequencer, then the behavior\nchanges for the user: currently you have to \"git commit\" after a\nconflict on cherry-pick. When it uses sequencer, you have to\ngit-sequencer --continue (or --skip or --abort) ;)\n\nSo I'm only concentrating on rebase and am users until the builtin sequencer\nis in good shape.\n\n> > +After resolving the conflict manually and updating the index with the\n> > +desired resolution, you can continue the sequencing process with\n> > +\n> > +    git sequencer --continue\n> \n> Does it run pre-commit hooks, for example checking for merge markers\n> (but also whitespace errors), and can those checks be disabled?\n\nIt only commits (git commit) staged changes (if the working tree is\nclean) and the pre-commit hooks are bypassed (as in rebase-i).\n\n> > +-B::\n> > +--batch::\n> > +\tRun in batch mode. If unexpected user intervention is needed\n> > +\t(e.g. a conflict or the need to run an editor), git-sequencer fails.\n> > ++\n> > +Note that the sanity check fails, if you use this option\n> > +and an instruction like `edit` or `pause`.\n> \n> s/.$/ is in the TODO file./\n\nAgreed.\n\ndiff --git a/Documentation/git-sequencer.txt b/Documentation/git-sequencer.txt\nindex e0c6410..1a9eda4 100644\n--- a/Documentation/git-sequencer.txt\n+++ b/Documentation/git-sequencer.txt\n@@ -62,7 +62,7 @@ OPTIONS\n \t(e.g. a conflict or the need to run an editor), git-sequencer fails.\n +\n Note that the sanity check fails, if you use this option\n-and an instruction like `edit` or `pause`.\n+and an instruction like `edit` or `pause` is in the TODO file.\n \n --onto=<base>::\n \tCheckout given commit or branch before sequencing.\n##\n\n> > +--edit::\n> > +\tInvoke editor to edit the undone rest of the TODO file.\n> \n> Does it mean that editor will be invoked with only _unprocessed_\n> part of the TODO file?  It looks like it, but it might be not\n> obvious to some.\n\nThanks, this sounds better.\n\n@@ -83,7 +83,7 @@ and an instruction like `edit` or `pause`.\n \toperations can be done to change that status.\n \n --edit::\n-\tInvoke editor to edit the undone rest of the TODO file.\n+\tInvoke editor to edit the unprocessed part of the TODO file.\n +\n The file is syntax- and sanity-checked afterwards, so that you can\n safely run `git sequencer --skip` or `--continue` after editing.\n##\n\n> > +merge [options] <commit-ish1> <commit-ish2> ... <commit-ishN>::\n> > +\tMerge commits into HEAD.\n> \n> Nice.\n> \n> \"HEAD\" mean last picked up / created commit, isn't it?\n\nRight. This is used throughout the document...\nI thought it is clear and better to use than always describing around it\nby \"last created commit\".\nBut currently I'm unsure about it :)\n\n> > ++\n> > +A commit can also be given by a mark, if prefixed with a colon.\n> \n> \"You can refer to commit by mark\", perhaps?\n\nHm, is \"by\" the right preposition?\n\n@@ -150,7 +150,7 @@ The set marks are removed after the sequencer has completed.\n merge [options] <commit-ish1> <commit-ish2> ... <commit-ishN>::\n \tMerge commits into HEAD.\n +\n-A commit can also be given by a mark, if prefixed with a colon.\n+You can refer to a commit by a mark.\n +\n If you do not provide a commit message (using `-F`, `-m`, `-C`, `-M`,\n or `--standard`), an editor will be invoked.\n##\n\n> > +\t--standard;;\n> > +\t\tGenerates a commit message like 'Merge ... into HEAD'.\n> > +\t\tSee also linkgit:git-fmt-merge-msg[1].\n> \n> Is it short for `--standard-message`?\n\nDo you think it should?\nSemantically it is less ambiguous, right, but\nas there is not short option, I think we should not make\nthe long options too long...\n\nPerhaps --std-msg?\n\n> > +pick [options] <commit>::\n> > +\tPick (see linkgit:git-cherry-pick[1]) a commit.\n> > +\tSequencer will pause on conflicts.\n> > ++\n> > +See the following list and 'GENERAL OPTIONS' for values of `options`:\n> > +\n> > +\t-R;;\n> > +\t--reverse;;\n> > +\t\tRevert the changes introduced by pick <commit>.\n> > +\n> > +\t--mainline=<n>;;\n> > +\t\tAllows you to pick merge commits by specifying the\n> > +\t\tparent number (beginning from 1) to let sequencer\n> > +\t\treplay the changes relative to the specified parent.\n> > +\t\t+\n> > +This option does not work together with `-R`.\n> \n> Why?  I would have thought that it would work...\n\ngit-revert has no --mainline option.\nWhen sequencer won't use cherry-pick/revert anymore, we can add that.\n\n> > +patch [options] <file>::\n> [...]\n> > +\t-*;;\n> > +\t\tAny other dash-prefixed option is passed to\n> > +\t\tlinkgit:git-apply[1].\n> > +\t\tThis is especially useful for flags like\n> > +\t\t`--reverse`, `-C<n>`, `-p<n>` or `--whitespace=<action>`.\n> \n> Do all options make sense?  What about `--index' and `--cached',\n> or about different no-apply options?\n\nNo, not all make sense and in fact the \"any other dash-prefixed option\"\nwas true some weeks ago, but now it's a lie. Now it is just a definite\nsubset and -C was renamed to --context due a conflict with the general\noption -C.\n\nThis is better:    (Lot of text copy&pasted from git-apply.txt)\n\n@@ -208,11 +208,50 @@ See the following list and 'GENERAL OPTIONS' for values of `options`:\n \t-n;;\n \t\tPass `-n` flag to `git-mailinfo` (see linkgit:git-mailinfo[1]).\n \n-\t-*;;\n-\t\tAny other dash-prefixed option is passed to\n-\t\tlinkgit:git-apply[1].\n-\t\tThis is especially useful for flags like\n-\t\t`--reverse`, `-C<n>`, `-p<n>` or `--whitespace=<action>`.\n+\t--exclude=<path-pattern>;;\n+\t\tDo not apply changes to files matching the given path pattern.\n+\t\tThis can be useful when importing patchsets, where you want to\n+\t\texclude certain files or directories.\n+\n+\t-R;;\n+\t--reverse;;\n+\t\tApply the patch in reverse.\n+\n+\t--no-add;;\n+\t\tWhen applying a patch, ignore additions made by the\n+\t\tpatch.  This can be used to extract the common part between\n+\t\ttwo files by first running `diff` on them and applying\n+\t\tthe result with this option, which would apply the\n+\t\tdeletion part but not addition part.\n+\n+\t--whitespace=<action>;;\n+\t\tSpecify behavior on whitespace errors.\n+\t\tSee linkgit:git-apply[1] for a detailed description.\n+\n+\t--context=<n>;;\n+\t\tEnsure at least <n> lines of surrounding context match before\n+\t\tand after each change.  When fewer lines of surrounding\n+\t\tcontext exist they all must match.  By default no context is\n+\t\tever ignored.\n+\n+\t--inaccurate-eof;;\n+\t\tUnder certain circumstances, some versions of diff do not\n+\t\tcorrectly detect a missing new-line at the end of the file.\n+\t\tAs a result, patches created by such diff programs do not\n+\t\trecord incomplete lines correctly.\n+\t\tThis option adds support for applying such patches by\n+\t\tworking around this bug.\n+\n+\t-p<n>;;\n+\t\tRemove <n> leading slashes from traditional diff paths.\n+\t\tThe default is 1.\n+\n+\t--unidiff-zero;;\n+\t\tBy default, linkgit:git-apply[1] expects that the patch being\n+\t\tapplied is a unified diff with at least one line of context.\n+\t\tThis provides good safety measures, but breaks down when\n+\t\tapplying a diff generated with --unified=0. To bypass these\n+\t\tchecks use '--unidiff-zero'.\n \n \n pause::\n##\n\n> > +ref <ref>::\n> > +\tSet ref `<ref>` to the current HEAD, see also\n> > +\tlinkgit:git-update-ref[1].\n> \n> So this functions like \"git reset --soft <ref>\", isn't it?\n\nNo. Why do you think that? `ref` is set, and not HEAD.\nI think the description makes that clear.\n\n> > +squash [options] --from <mark>::\n> > +\tSquash all commits from the given mark into one commit.\n> > +\tThere must not be any `merge` instructions between the\n> > +\t`mark` instruction and this `squash --from` instruction.\n> \n> Can you use <commit> instead of <mark> here?\n\nI wanted to make it clear that you can only specify a mark:\na commit that has been somehow used in this sequencer session.\n\nOr have you meant that you think it is a bad restriction to only\nallow marks and no commits?\nI think this is a useful thing, because it's user-safe and I\ncannot imagine a case where you want to give a sha1 or a\ntag or branch or something.\n\nHere an example why it is useful for user-editing:\n\n(on commit f00babe)\n\tmark :1\n\tpick badcebab\n\tpatch foo\n\tpick dadadada\n\tsquash -m \"Foo the cebab\" --signoff --from :1\n\nThis squashes all between the mark and the squash into one commit,\non top of f00babe.\n\nIf we allow commits, the user could think that\n\n\tpick badcebab\n\tpatch foo\n\tpick dadadada\n\tsquash -m \"Foo the cebab\" --signoff --from badcebab\n\ndoes the same, but this leads to:\n f00babe, picked-badcebab, squash-of-foo-and-dadadada\n\nSo\n\tsquash -m \"Foo the cebab\" --signoff --from f00babe\nwould be correct.  But this is unintuitive.\nSo it's safer if we restrict this to marks.\n\n> > +\t--include-merges;;\n> > +\t\tSanity check does not fail if you have merges\n> > +\t\tbetween HEAD and <mark>.\n> \n> How do you squash merges?  Creating merge with an union of parents,\n> excluding commits which got squashed?\n\nMy squashes are realized using git reset --soft ... and then commit.\nI think this makes only sense when there are no merges in between,\nso I added the check, but if someone wants to squash merges, he should\nbe able to do it.\nTo somehow answer your question: I do not care what the result is,\nbecause I do not know what the result \"should be\".\nIIRC the \"other\" parents of the merge commit are not kept, so it seems\nthat you have a commit that contains the changes after the merge, but\nnot the meta information like the right parents.\n\n> It means\n> \n>   ...a---b---c---d         ...[abcd]\n>             /        ==>        /\n>       ...x-/               ..x-/\n> \n> but\n> \n>   ...a---b---c---d          ...[abcd]\n>       \\     /        ==>\n>        \\-x-/ \n> \n\nI think it will be ...[abcdx].\n\nBut as I said, \"I don't care\". And the help description shows that.\n\n> > +RETURN VALUES\n> > +-------------\n> > +* any other value on error, e.g.\n> > +  running git-sequencer on a bare repository.\n> \n> Don't you enumerate those return values?\n\nIn one of the very first spec versions, it was value 1, but:\n\n\t$ grep -A 3 ^die git-sh-setup\n\tdie() {\n\t\techo >&2 \"$@\"\n\t\texit 1\n\t}\n\n\t$ grep -m 1 -A 4 die_builtin usage.c\n\tstatic NORETURN void die_builtin(const char *err, va_list params)\n\t{\n\t\treport(\"fatal: \", err, params);\n\t\texit(128);\n\t}\n\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"81896","messageId":"200807012004.11563.jnareb@gmail.com","threadId":"14239","inReplyTo":"20080701160322.GC5301@leksak.fem-net","subject":"Re: [RFC/PATCH 2/4] Add git-sequencer prototype documentation","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-07-01T18:04:10Z","receivedAt":"2008-07-01T18:04:10Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Hi,\n\nOn Tue, 1 Jul 2008, Stephan Beyer wrote:\n> On Tue, Jul 01, 2008 at 06:02:54AM -0700,\n> Jakub Narebski <jnareb@gmail.com> wrote:\n>> Stephan Beyer wrote:\n>>>\n>>> +git-sequencer will usually be called by another git porcelain, like\n>>> +linkgit:git-am[1] or linkgit:git-rebase[1].\n>> \n>> I hope that it could be also used by git-cherry-pick and git-revert,\n>> so it would be possible to pick more than one commit...\n> \n> Right, you've already mentioned it several times. ;-)\n\n:blush: I'm sorry about that...\n\n> But I haven't included it currently, because git-sequencer currently *uses*\n> cherry-pick/revert to pick/revert commits, and I think this can lead to\n> some confusion.\n[...]\n> So I'm only concentrating on rebase and am users until the builtin sequencer\n> is in good shape.\n\nAh, I understand.  It _is_ quite reasonable.\n\n>>> +merge [options] <commit-ish1> <commit-ish2> ... <commit-ishN>::\n>>> +\tMerge commits into HEAD.\n>> \n>> Nice.\n>> \n>> \"HEAD\" mean last picked up / created commit, isn't it?\n> \n> Right. This is used throughout the document...\n> I thought it is clear and better to use than always describing around it\n> by \"last created commit\".\n\nO.K.\n\n>>> +ref <ref>::\n>>> +\tSet ref `<ref>` to the current HEAD, see also\n>>> +\tlinkgit:git-update-ref[1].\n>> \n>> So this functions like \"git reset --soft <ref>\", isn't it?\n> \n> No. Why do you think that? `ref` is set, and not HEAD.\n> I think the description makes that clear.\n\nAh.  I'm sorry.  So it is like \"git branch <ref>\", isn't it?\n\nWhat is important is: does it update reflog (correctly)?\n \n>>> +squash [options] --from <mark>::\n>>> +\tSquash all commits from the given mark into one commit.\n>>> +\tThere must not be any `merge` instructions between the\n>>> +\t`mark` instruction and this `squash --from` instruction.\n>> \n>> Can you use <commit> instead of <mark> here?\n> \n> I wanted to make it clear that you can only specify a mark:\n> a commit that has been somehow used in this sequencer session.\n> \n> Or have you meant that you think it is a bad restriction to only\n> allow marks and no commits?\n> I think this is a useful thing, because it's user-safe and I\n> cannot imagine a case where you want to give a sha1 or a\n> tag or branch or something.\n> \n> Here an example why it is useful for user-editing:\n> \n> (on commit f00babe)\n> \tmark :1\n> \tpick badcebab\n> \tpatch foo\n> \tpick dadadada\n> \tsquash -m \"Foo the cebab\" --signoff --from :1\n> \n> This squashes all between the mark and the squash into one commit,\n> on top of f00babe.\n \nAh, so squash --from <mark> picks up everything since \"mark <mark>\",\nbut does not include marked commit!  Clever!  In this case allowing\nonly <mark> is a good idea, IMVHO.\n \n>>> +\t--include-merges;;\n>>> +\t\tSanity check does not fail if you have merges\n>>> +\t\tbetween HEAD and <mark>.\n>> \n>> How do you squash merges?  Creating merge with an union of parents,\n>> excluding commits which got squashed?\n> \n> My squashes are realized using git reset --soft ... and then commit.\n> I think this makes only sense when there are no merges in between,\n> so I added the check, but if someone wants to squash merges, he should\n> be able to do it.\n>\n> To somehow answer your question: I do not care what the result is,\n> because I do not know what the result \"should be\".\n\nO.K.  I guess that is something left for later, especially that\nforbidding merges in squashed commit is default (and you can always\ndo without merges, I think).\n\n>>> +RETURN VALUES\n>>> +-------------\n>>> +* any other value on error, e.g.\n>>> +  running git-sequencer on a bare repository.\n>> \n>> Don't you enumerate those return values?\n> \n> In one of the very first spec versions, it was value 1, but:\n[...]\n> \t$ grep -m 1 -A 4 die_builtin usage.c\n> \tstatic NORETURN void die_builtin(const char *err, va_list params)\n> \t{\n> \t\treport(\"fatal: \", err, params);\n> \t\texit(128);\n> \t}\n\nPerhaps stating that it returns 128 on fatal error, or rewording\nthat any other return value means some fatal error (does it?)\nwould be better.  But that are details...\n\n-- \nJakub Narebski\nPoland\n"},{"id":"81901","messageId":"20080701195033.GD5301@leksak.fem-net","threadId":"14239","inReplyTo":"200807012004.11563.jnareb@gmail.com","subject":"Re: [RFC/PATCH 2/4] Add git-sequencer prototype documentation","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-01T19:50:33Z","receivedAt":"2008-07-01T19:50:33Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn Tue, Jul 01, 2008 at 08:04:10PM +0200, Jakub Narebski wrote:\n> On Tue, 1 Jul 2008, Stephan Beyer wrote:\n> > On Tue, Jul 01, 2008 at 06:02:54AM -0700,\n> > Jakub Narebski <jnareb@gmail.com> wrote:\n> >> Stephan Beyer wrote:\n> >>> +merge [options] <commit-ish1> <commit-ish2> ... <commit-ishN>::\n> >>> +\tMerge commits into HEAD.\n> >> \n> >> Nice.\n> >> \n> >> \"HEAD\" mean last picked up / created commit, isn't it?\n> > \n> > Right. This is used throughout the document...\n> > I thought it is clear and better to use than always describing around it\n> > by \"last created commit\".\n> \n> O.K.\n\nI don't know.  If something like \"last created commit\" is better,\nI have no problem to change it :)\n\n> >>> +ref <ref>::\n> >>> +\tSet ref `<ref>` to the current HEAD, see also\n> >>> +\tlinkgit:git-update-ref[1].\n> >> \n> >> So this functions like \"git reset --soft <ref>\", isn't it?\n> > \n> > No. Why do you think that? `ref` is set, and not HEAD.\n> > I think the description makes that clear.\n> \n> Ah.  I'm sorry.  So it is like \"git branch <ref>\", isn't it?\n\nNo. It is \"git-update-ref <ref> HEAD\".\n\n> What is important is: does it update reflog (correctly)?\n\nGood question. The reflog is another mistery to me that I haven't really\ncared about, because I haven't used it yet myself.\nAt least the reflog test cases for git rebase -i in the test suite pass.\n(Of course, this is only a weak indication that it works as it should.)\n\n> >>> +squash [options] --from <mark>::\n[...]\n> > Here an example why it is useful for user-editing:\n> > \n> > (on commit f00babe)\n> > \tmark :1\n> > \tpick badcebab\n> > \tpatch foo\n> > \tpick dadadada\n> > \tsquash -m \"Foo the cebab\" --signoff --from :1\n> > \n> > This squashes all between the mark and the squash into one commit,\n> > on top of f00babe.\n>  \n> Ah, so squash --from <mark> picks up everything since \"mark <mark>\",\n> but does not include marked commit!  Clever!  In this case allowing\n> only <mark> is a good idea, IMVHO.\n\nGood, thanks :)\n\n> >>> +\t--include-merges;;\n> >>> +\t\tSanity check does not fail if you have merges\n> >>> +\t\tbetween HEAD and <mark>.\n> >> \n> >> How do you squash merges?  Creating merge with an union of parents,\n> >> excluding commits which got squashed?\n> > \n> > My squashes are realized using git reset --soft ... and then commit.\n> > I think this makes only sense when there are no merges in between,\n> > so I added the check, but if someone wants to squash merges, he should\n> > be able to do it.\n> >\n> > To somehow answer your question: I do not care what the result is,\n> > because I do not know what the result \"should be\".\n> \n> O.K.  I guess that is something left for later, especially that\n> forbidding merges in squashed commit is default (and you can always\n> do without merges, I think).\n\nForbidding merges is default currently. It's just a sanity check. And\nthe option bypasses this check.\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"81912","messageId":"200807020239.41613.jnareb@gmail.com","threadId":"14239","inReplyTo":"20080701195033.GD5301@leksak.fem-net","subject":"Re: [RFC/PATCH 2/4] Add git-sequencer prototype documentation","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-07-02T00:39:40Z","receivedAt":"2008-07-02T00:39:40Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Hi!\n\nOn Tue, 1 July 2008, Stephan Beyer wrote:\n> On Tue, Jul 01, 2008 at 08:04:10PM +0200, Jakub Narebski wrote:\n>> On Tue, 1 Jul 2008, Stephan Beyer wrote:\n>>> On Tue, Jul 01, 2008 at 06:02:54AM -0700,\n>>> Jakub Narebski <jnareb@gmail.com> wrote:\n>>>> Stephan Beyer wrote:\n[...]\n>>>>> +ref <ref>::\n>>>>> +\tSet ref `<ref>` to the current HEAD, see also\n>>>>> +\tlinkgit:git-update-ref[1].\n>>>> \n>>>> So this functions like \"git reset --soft <ref>\", isn't it?\n>>> \n>>> No. Why do you think that? `ref` is set, and not HEAD.\n>>> I think the description makes that clear.\n>> \n>> Ah.  I'm sorry.  So it is like \"git branch <ref>\", isn't it?\n\nActually I meant \"git branch -f <ref>\" here.  But I forgot that it\ncan be used to create lightweight tags, too.\n\n> No. It is \"git-update-ref <ref> HEAD\".\n\nSo what do you envision would this be used for?\n\n>> What is important is: does it update reflog (correctly)?\n> \n> Good question. The reflog is another mistery to me that I haven't really\n> cared about, because I haven't used it yet myself.\n> At least the reflog test cases for git rebase -i in the test suite pass.\n> (Of course, this is only a weak indication that it works as it should.)\n\nYou have 'branch' (<onto>) reflog, HEAD reflog, and reflog for '<ref>'.\nWhile 'branch' reflog should I think record only start and end of\nsequencer, or rather git-am or git-rebase, I'm not sure what to do about\nHEAD reflog...  We should fill reflog for <ref>, to be able to revert\neasily.\n\n>>>>> +squash [options] --from <mark>::\n> [...]\n>>> Here an example why it is useful for user-editing:\n>>> \n>>> (on commit f00babe)\n>>> \tmark :1\n>>> \tpick badcebab\n>>> \tpatch foo\n>>> \tpick dadadada\n>>> \tsquash -m \"Foo the cebab\" --signoff --from :1\n>>> \n>>> This squashes all between the mark and the squash into one commit,\n>>> on top of f00babe.\n>>  \n>> Ah, so squash --from <mark> picks up everything since \"mark <mark>\",\n>> but does not include marked commit!  Clever!  In this case allowing\n>> only <mark> is a good idea, IMVHO.\n> \n> Good, thanks :)\n\nAlthough I guess having example would make it clear from the go...\n\nGood work!\n-- \nJakub Narebski\nPoland\n"},{"id":"81913","messageId":"7v4p79hyk0.fsf@gitster.siamese.dyndns.org","threadId":"14239","inReplyTo":"200807020239.41613.jnareb@gmail.com","subject":"Re: [RFC/PATCH 2/4] Add git-sequencer prototype documentation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-02T01:20:15Z","receivedAt":"2008-07-02T01:20:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n>> No. It is \"git-update-ref <ref> HEAD\".\n>\n> So what do you envision would this be used for?\n\nA simple answer and a more elaborate one.\n\n * It is the final step of \"git rebase\" which detaches HEAD while it\n   operates these days.\n\n * You can drive sequencer backend from a front-end that rewrite history\n   while rewriting tags, like filter-branch does.\n\n>>> What is important is: does it update reflog (correctly)?\n\nThat is not very important question, as reflog updates would happen as\nlong as you use update-ref automatically.\n\nMuch more important question you did not ask is how it would interact with\n\"sequencer --abort\".  Ideally it should rewind the ref update (and without\nrelying on the user having reflog on that ref).\n\nI however personally feel that this \"ref\" thing is being a bit too\nambitious.\n"},{"id":"81919","messageId":"20080702030135.GF5301@leksak.fem-net","threadId":"14239","inReplyTo":"7v4p79hyk0.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC/PATCH 2/4] Add git-sequencer prototype documentation","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-02T03:01:35Z","receivedAt":"2008-07-02T03:01:35Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"On Wed, Jul 02, 2008 at 02:39:40AM +0200, Jakub Narebski wrote:\n> On Tue, 1 July 2008, Stephan Beyer wrote:\n> > On Tue, Jul 01, 2008 at 08:04:10PM +0200, Jakub Narebski wrote:\n[...]\n> > No. It is \"git-update-ref <ref> HEAD\".\n> \n> So what do you envision would this be used for?\n\nI think if I had not started on top js/rebase-i-sequencer, I would have\nnot necessarily added \"ref\" (or \"tag\", as it was before).\nBut js/rebase-i-sequencer introduced a nice feature to\ngit-rebase-i:\n -t,--preserve-tags ... \"update tags to the new commit object\"\n\nI think this is worth the feature ;-)\n\nOn Tue, Jul 01, 2008 at 06:20:15PM -0700, Junio C Hamano wrote:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n> >> No. It is \"git-update-ref <ref> HEAD\".\n> >\n> > So what do you envision would this be used for?\n> \n> A simple answer and a more elaborate one.\n> \n>  * It is the final step of \"git rebase\" which detaches HEAD while it\n>    operates these days.\n\nHa ;)\nThat's a quite obvious truth that I have not implemented.\nBtw: sequencer does the detaching/attaching when using \"--onto <base>\"\nand <base> is a branch.\nIIRC there was a reason that I also kept the detaching/attaching of\ngit-rebase-i itself but I can't remember. (I think I have to look\nover the rebase-i code more carefully later...)\n\n>  * You can drive sequencer backend from a front-end that rewrite history\n>    while rewriting tags, like filter-branch does.\n\nYes.\n\n> >>> What is important is: does it update reflog (correctly)?\n> \n> That is not very important question, as reflog updates would happen as\n> long as you use update-ref automatically.\n> \n> Much more important question you did not ask is how it would interact with\n> \"sequencer --abort\".  Ideally it should rewind the ref update (and without\n> relying on the user having reflog on that ref).\n\nYes, you asked the question in the RFC thread about the spec.\n\n\"Rewind the ref update\" means:\n - delete new generated refs\n - update overwritten refs to their old commits\nSo if I keep a list containing <ref> [<oldcommit>], that behavior\nis easily reached. But this is not suited for the shell prototype ;)\n\n\nBtw, also the --skip case can be arguable:\n\n\tpick fa1afe1\n\tpick cedefe1\t# conflict, will be \"--skip\"ped\n\tref refs/tags/v1.6.2\n\nHere the question can be, if the \"ref\" should be skipped, too.\nBut I think the just-don't-care-strategy is a good one, so\nthat fa1afe1' will be tagged.\n\n> I however personally feel that this \"ref\" thing is being a bit too\n> ambitious.\n\nI agree that it is no must-have feature but a nice-to-have feature ;)\nEspecially for the --preserve-tags feature.\n\n\nJakub wrote:\n> >>>>> +squash [options] --from <mark>::\n> > [...]\n> >>> Here an example why it is useful for user-editing:\n> >>> \n> >>> (on commit f00babe)\n> >>> \tmark :1\n> >>> \tpick badcebab\n> >>> \tpatch foo\n> >>> \tpick dadadada\n> >>> \tsquash -m \"Foo the cebab\" --signoff --from :1\n> >>> \n> >>> This squashes all between the mark and the squash into one commit,\n> >>> on top of f00babe.\n> >>  \n> >> Ah, so squash --from <mark> picks up everything since \"mark <mark>\",\n> >> but does not include marked commit!  Clever!  In this case allowing\n> >> only <mark> is a good idea, IMVHO.\n> > \n> > Good, thanks :)\n> \n> Although I guess having example would make it clear from the go...\n\nYes, I see that the EXAMPLES section is really important and the\nsquash --from is important therein.\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82063","messageId":"7vbq1f68rh.fsf@gitster.siamese.dyndns.org","threadId":"14239","inReplyTo":"1214879914-17866-2-git-send-email-s-beyer@gmx.net","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-03T01:45:06Z","receivedAt":"2008-07-03T01:45:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephan Beyer <s-beyer@gmx.net> writes:\n\n> git sequencer is planned as a backend for user scripts\n> that execute a sequence of git instructions and perhaps\n> need manual intervention, for example git-rebase or git-am.\n\n...\n> +output () {\n> +\tcase \"$VERBOSE\" in\n> +\t0)\n> +\t\t\"$@\" >/dev/null\n> +\t\t;;\n> +\t1)\n> +\t\toutput=$(\"$@\" 2>&1 )\n> +\t\tstatus=$?\n> +\t\ttest $status -ne 0 && printf '%s\\n' \"$output\"\n> +\t\treturn $status\n> +\t\t;;\n> +\t2)\n> +\t\t\"$@\"\n> +\t\t;;\n> +\tesac\n> +}\n\nPerhaps misnamed?  This feels more like \"do\" or \"perform\" or \"run\".\n\n> +require_clean_work_tree () {\n> +\t# test if working tree is dirty\n> +\tgit rev-parse --verify HEAD >/dev/null &&\n> +\tgit update-index --ignore-submodules --refresh &&\n> +\tgit diff-files --quiet --ignore-submodules &&\n> +\tgit diff-index --cached --quiet HEAD --ignore-submodules -- ||\n> +\tdie 'Working tree is dirty'\n> +}\n\nWhen is it necessary to ignore submodules and why?  Are there cases where\nsubmodules should not be ignored?\n\n> +LAST_COUNT=\n> +mark_action_done () {\n> +\tsed -e 1q <\"$TODO\" >>\"$DONE\"\n> +\tsed -e 1d <\"$TODO\" >\"$TODO.new\"\n> +\tmv -f \"$TODO.new\" \"$TODO\"\n> +\tif test \"$VERBOSE\" -gt 0\n> +\tthen\n> +\t\tcount=$(grep -c '^[^#]' <\"$DONE\")\n> +\t\ttotal=$(expr \"$count\" + \"$(grep -c '^[^#]' <\"$TODO\")\")\n\nHere we are not counting lines that are comments as insns (I am not\ncomplaining; just making a mental note).\n\n> +\t\tif test \"$LAST_COUNT\" != \"$count\"\n> +\t\tthen\n> +\t\t\tLAST_COUNT=\"$count\"\n> +\t\t\ttest \"$VERBOSE\" -lt 1 ||\n> +\t\t\t\tprintf 'Sequencing (%d/%d)\\r' \"$count\" \"$total\"\n> +\t\t\ttest \"$VERBOSE\" -lt 2 || echo\n> +\t\tfi\n> +\tfi\n> +}\n> +\n> +# Generate message, patch and author script files\n> +make_patch () {\n> +\tparent_sha1=$(git rev-parse --verify \"$1\"^) ||\n> +\t\tdie \"Cannot get patch for $1^\"\n> +\tgit diff-tree -p \"$parent_sha1..$1\" >\"$PATCH\"\n\nCould there be a case where we need/want to deal with a root commit\nwithout parents?\n\n> +\ttest -f \"$MSG\" ||\n> +\t\tcommit_message \"$1\" >\"$MSG\"\n> +\ttest -f \"$AUTHOR_SCRIPT\" ||\n> +\t\tget_author_ident_from_commit \"$1\" >\"$AUTHOR_SCRIPT\"\n> +}\n> +\n> +# Generate a patch and die with \"conflict\" status code\n> +die_with_patch () {\n> +\tmake_patch \"$1\"\n> +\tgit rerere\n> +\tdie_to_continue \"$2\"\n> +}\n> +\n> +restore () {\n> +\tgit rerere clear\n> +\n> +\tHEADNAME=$(cat \"$SEQ_DIR/head-name\")\n> +\tHEAD=$(cat \"$SEQ_DIR/head\")\n\nPerhaps\n\n\tread HEADNAME <\"$SEQ_DIR/head-name\"\n\nprovided if these values are $IFS safe?\n\n> +\tcase $HEADNAME in\n> +\trefs/*)\n> +\t\tgit symbolic-ref HEAD \"$HEADNAME\"\n> +\t\t;;\n> +\tesac &&\n> +\toutput git reset --hard \"$HEAD\"\n> +}\n> +\n> +has_action () {\n> +\tgrep '^[^#]' \"$1\" >/dev/null\n> +}\n> +\n> +# Check if text file $1 contains a commit message\n> +has_message () {\n> +\ttest -n \"$(sed -n -e '/^Signed-off-by:/d;/^[^#]/p' <\"$1\")\"\n> +}\n\nMakes one wonder if we would want to special case other kinds like\n\"Acked-by:\" as well...\n\n> +# Usage: pick_one (cherry-pick|revert) [-*|--edit] sha1\n> +pick_one () {\n> +\twhat=\"$1\"\n> +\t# we just assume that this is either cherry-pick or revert\n> +\tshift\n> +\n> +\t# check for fast-forward if no options are given\n> +\tif expr \"x$1\" : 'x[^-]' >/dev/null\n> +\tthen\n> +\t\ttest \"$(git rev-parse --verify \"$1^\")\" = \\\n> +\t\t\t\"$(git rev-parse --verify HEAD)\" &&\n> +\t\t\toutput git reset --hard \"$1\" &&\n> +\t\t\treturn\n> +\tfi\n> +\ttest \"$1\" != '--edit' -a \"$what\" = 'revert' &&\n> +\t\twhat='revert --no-edit'\n\nThis looks somewhat wrong.\n\nWhen the history looks like ---A---B and we are at A, cherry-picking B can\nbe optimized to just advancing to B, but that optimization has a slight\ndifference (or two) in the semantics.\n\n (1) The committer information would not record the user and time of the\n     sequencer operation, which actually may be a good thing.\n\n (2) When $what is revert, this codepath shouldn't be exercised, should it?\n\n (3) If B is a merge, even if $what is pick, this codepath shouldn't be\n     exercised, should it?\n\nAs to the syntax I tend to prefer\n\n\tcase \"$1\" in\n        -*)\t... do option thing ... ;;\n        *)\t... do other thing... ;;\n        esac\n\nSo how about...\n\n\tcase \"$what,$1\" in\n        revert,--edit)\n        \twhat='revert --no-edit' ;;\n        revert,* | cherry-pick,-* )\n        \t;;\n        *)\n\t\tif ! git rev-parse --verify \"$1^2\" &&\n\t                test \"$(git rev-parse --verify \"$1^\") = \\\n                \t\"$(git rev-parse --verify HEAD)\"\n\t\tthen\n                \toutput git reset --hard \"$1\"\n\t\t\treturn\n\t\tfi\n\t\t;;\n\tesac\n\n> +make_squash_message () {\n> +\tif test -f \"$squash_msg\"\n> +\tthen\n> +\t\tcount=$(($(sed -n -e 's/^# This is [^0-9]*\\([1-9][0-9]*\\).*/\\1/p' \\\n> +\t\t\t<\"$squash_msg\" | sed -n -e '$p')+1))\n> +\t\techo \"# This is a combination of $count commits.\"\n> +\t\tsed -e '1d' -e '2,/^./{\n> +\t\t\t/^$/d\n> +\t\t}' <\"$squash_msg\"\n> +\telse\n> +\t\tcount=2\n> +\t\techo '# This is a combination of 2 commits.'\n> +\t\techo '# The first commit message is:'\n> +\t\techo\n> +\t\tcommit_message HEAD\n> +\tfi\n> +\techo\n> +\techo \"# This is the $(nth_string \"$count\") commit message:\"\n> +\techo\n> +\tcommit_message \"$1\"\n> +}\n> +\n> +make_squash_message_multiple () {\n> +\techo '# This is a dummy to get the 0.' >\"$squash_msg\"\n> +\tfor cur_sha1 in $(git rev-list --reverse \"$sha1..HEAD\")\n> +\tdo\n> +\t\tmake_squash_message \"$cur_sha1\" >\"$MSG\"\n> +\t\tcp \"$MSG\" \"$squash_msg\"\n> +\tdone\n> +}\n\nHmm, I know this is how rebase-i is written, but we should be able to do\nbetter than writing and flipping temporary times N times, shouldn't we?\n\n> +peek_next_command () {\n> +\tsed -n -e '1s/ .*$//p' <\"$TODO\"\n> +}\n\n... which could respond \"the next command is '#' (comment)\", so we are\nactively counting a comment as a step here.  Does this contradict with the\nmental note we made earlier, and if so, does the discrepancy hurt us\nsomewhere in this program?\n\n> +# If $1 is a mark, make a ref from it; otherwise keep it\n> +mark_to_ref () {\n> +\targ=\"$1\"\n> +\tref=$(expr \"x$arg\" : 'x:0*\\([0-9][0-9]*\\)$')\n\nYou might want to leave comments to describe constraints that led to this\nslightly awkward regexp:\n\n * :0 is allowed\n * :01 is the same as :1\n\n> +strategy_check () {\n> +\tcase \"$1\" in\n> +\tresolve|recursive|octopus|ours|subtree|theirs)\n> +\t\treturn\n> +\t\t;;\n> +\tesac\n> +\ttodo_warn \"Strategy '$1' not known.\"\n> +}\n\nHmm.  Do we need to maintain list of available strategies here and then in\ngit-merge separately?\n\n> +### Author script functions\n> +\n> +clean_author_script () {\n> +\tcat \"$ORIG_AUTHOR_SCRIPT\" >\"$AUTHOR_SCRIPT\"\n> +}\n> +\n> +# Take \"Name <e-mail>\" in stdin and outputs author script\n> +make_author_script_from_string () {\n> +\tsed -e 's/^\\(.*\\) <\\(.*\\)>.*$/GIT_AUTHOR_NAME=\"\\1\"\\\n> +GIT_AUTHOR_EMAIL=\"\\2\"\\\n> +GIT_AUTHOR_DATE=/'\n> +}\n\nIf you are going to \".\"-source or eval the output from this, you would\nneed to quote the values a lot more robustly, wouldn't you?  Is this safe\nagainst shell metacharacters in names, mails and/or space between unixtime\nand the timezone information?\n\n> +\tif test -z \"$AUTHOR\"\n> +\tthen\n> +\t\tsed -n -e '\n> +\t\t\ts/^Author: \\(.*\\)$/GIT_AUTHOR_NAME=\"\\1\"/p;\n> +\t\t\ts/^Email: \\(.*\\)$/GIT_AUTHOR_EMAIL=\"\\1\"/p;\n> +\t\t\ts/^Date: \\(.*\\)$/GIT_AUTHOR_DATE=\"\\1\"/p\n> +\t\t' <\"$infofile\" >>\"$AUTHOR_SCRIPT\"\n\nThe same comment on quoting applies here, I think.\n\n> +\t\t# If sed's result is empty, we keep the original\n> +\t\t# author script by appending.\n> +\tfi\n> ...\n> +\tfailed=\n> +\twith_author git apply $apply_opts --index \"$PATCH\" || failed=t\n> +\n> +\tif test -n \"$failed\" -a -n \"$threeway\" && (with_author fallback_3way)\n> +\tthen\n> +\t\t# Applying the patch to an earlier tree and merging the\n> +\t\t# result may have produced the same tree as ours.\n> +\t\tgit diff-index --quiet --cached HEAD -- && {\n> +\t\t\techo 'No changes -- Patch already applied.'\n> +\t\t\treturn 0\n> +\t\t\t# XXX: do we want that?\n> +\t\t}\n> +\t\t# clear apply_status -- we have successfully merged.\n> +\t\tfailed=\n> +\tfi\n> +\n> +\tif test -n \"$failed\"\n> +\tthen\n> +\t\t# XXX: This is just a stupid hack:\n> +\t\twith_author git apply $apply_opts --reject --index \"$PATCH\"\n\nPlease don't do this without being asked, if you are planning to use this\nin \"am\" when 3-way fallback was not asked.  It _may_ make sense to give an\noption to the users to ask for .rej if they prefer to work that way better\nthan working with 3-way merge fallback, but doing this without being asked\nis not acceptable.\n\n> +\t\tdie_to_continue 'Patch failed. See the .rej files.'\n> +\t\t# XXX: We actually needed a git-apply flag that creates\n> +\t\t# conflict markers and sets the DIFF_STATUS_UNMERGED flag.\n\nThat is what -3way is all about, and this codepath is when the user did\nnot ask for it, isn't it?\n\n> +# Check the \"pick\" instruction\n> +check_pick () {\n> +\trevert=\n> +\tmainline=\n> +\twhile test $# -gt 1\n> +\tdo\n> ...\n> +\tdone\n> +\n> +\tif test -n \"$mainline\"\n> +\tthen\n> +\t\ttest -z \"$revert\" ||\n> +\t\t\ttodo_error \"Cannot use $revert together with --mainline.\"\n\nWhy not?  If you have this...\n\n\t---A---C---D\n              /\n          ---B\n\nand you are at D, you may want to undo the merge you made at C and go back\nto either A or B, which essentially is same as cherry-picking diff between\nC and D on top of either A or B.  Both are valid operations aren't they?\n\nThe remainder of the review will have to be in a separate message..\n"},{"id":"82107","messageId":"alpine.DEB.1.00.0807031142540.9925@racer","threadId":"14239","inReplyTo":"7vbq1f68rh.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-07-03T11:03:49Z","receivedAt":"2008-07-03T11:03:49Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 2 Jul 2008, Junio C Hamano wrote:\n\n> Stephan Beyer <s-beyer@gmx.net> writes:\n> \n> > git sequencer is planned as a backend for user scripts\n> > that execute a sequence of git instructions and perhaps\n> > need manual intervention, for example git-rebase or git-am.\n> \n> ...\n> > +output () {\n> > +\tcase \"$VERBOSE\" in\n> > +\t0)\n> > +\t\t\"$@\" >/dev/null\n> > +\t\t;;\n> > +\t1)\n> > +\t\toutput=$(\"$@\" 2>&1 )\n> > +\t\tstatus=$?\n> > +\t\ttest $status -ne 0 && printf '%s\\n' \"$output\"\n> > +\t\treturn $status\n> > +\t\t;;\n> > +\t2)\n> > +\t\t\"$@\"\n> > +\t\t;;\n> > +\tesac\n> > +}\n> \n> Perhaps misnamed?  This feels more like \"do\" or \"perform\" or \"run\".\n\nMy fault.  I like \"perform\".\n\n> > +require_clean_work_tree () {\n> > +\t# test if working tree is dirty\n> > +\tgit rev-parse --verify HEAD >/dev/null &&\n> > +\tgit update-index --ignore-submodules --refresh &&\n> > +\tgit diff-files --quiet --ignore-submodules &&\n> > +\tgit diff-index --cached --quiet HEAD --ignore-submodules -- ||\n> > +\tdie 'Working tree is dirty'\n> > +}\n> \n> When is it necessary to ignore submodules and why?\n\nSubmodules are not updated by checkout.  Indeed, the _only_ Git command \nthat actually changes the state of a submodule is \"git submodule update\".\n\nTherefore, it is wrong to assume that rebase/am/whatever works with \nsubmodules as far as the working directory is concerned.  Updating \nsubmodules with any Git command other than \"git submodule update\" is a \n_pure_ index operation.\n\nOf course, that means that if you use rebase -i's \"edit\" command to go \nback to a certain revision, edit that, and want to test, it is _your_ \nresponsibility to make sure that the submodules are at their correct \nrevision.\n\n> Are there cases where submodules should not be ignored?\n\nWith above reasoning, it would always be wrong for sequencer to require \nthe submodules to be up-to-date.\n\n> > +LAST_COUNT=\n> > +mark_action_done () {\n> > +\tsed -e 1q <\"$TODO\" >>\"$DONE\"\n> > +\tsed -e 1d <\"$TODO\" >\"$TODO.new\"\n> > +\tmv -f \"$TODO.new\" \"$TODO\"\n> > +\tif test \"$VERBOSE\" -gt 0\n> > +\tthen\n> > +\t\tcount=$(grep -c '^[^#]' <\"$DONE\")\n> > +\t\ttotal=$(expr \"$count\" + \"$(grep -c '^[^#]' <\"$TODO\")\")\n> \n> Here we are not counting lines that are comments as insns (I am not\n> complaining; just making a mental note).\n\nAs \"count\" and \"total\" are only used for the progress output, anything \nelse would not make sense.\n\n> > +\t\tif test \"$LAST_COUNT\" != \"$count\"\n> > +\t\tthen\n> > +\t\t\tLAST_COUNT=\"$count\"\n> > +\t\t\ttest \"$VERBOSE\" -lt 1 ||\n> > +\t\t\t\tprintf 'Sequencing (%d/%d)\\r' \"$count\" \"$total\"\n> > +\t\t\ttest \"$VERBOSE\" -lt 2 || echo\n> > +\t\tfi\n> > +\tfi\n> > +}\n> > +\n> > +# Generate message, patch and author script files\n> > +make_patch () {\n> > +\tparent_sha1=$(git rev-parse --verify \"$1\"^) ||\n> > +\t\tdie \"Cannot get patch for $1^\"\n> > +\tgit diff-tree -p \"$parent_sha1..$1\" >\"$PATCH\"\n> \n> Could there be a case where we need/want to deal with a root commit\n> without parents?\n\nYes.  I had exactly that need a few days ago, where I wanted to import a \nfew zips, and rebase them on top of an existing branch (which was \ngenerated in the same manner).\n\nI worked around that limitation of rebase (actually, I only tried rebase \n-i, come to think of it), by rewriting the first commit object, inserting \nthe \"parent\" line.  \"fast-export > a1; vi a1; fast-import < a1\" can be so \nmuch fun!\n\n> > +\ttest -f \"$MSG\" ||\n> > +\t\tcommit_message \"$1\" >\"$MSG\"\n> > +\ttest -f \"$AUTHOR_SCRIPT\" ||\n> > +\t\tget_author_ident_from_commit \"$1\" >\"$AUTHOR_SCRIPT\"\n> > +}\n> > +\n> > +# Generate a patch and die with \"conflict\" status code\n> > +die_with_patch () {\n> > +\tmake_patch \"$1\"\n> > +\tgit rerere\n> > +\tdie_to_continue \"$2\"\n> > +}\n> > +\n> > +restore () {\n> > +\tgit rerere clear\n> > +\n> > +\tHEADNAME=$(cat \"$SEQ_DIR/head-name\")\n> > +\tHEAD=$(cat \"$SEQ_DIR/head\")\n> \n> Perhaps\n> \n> \tread HEADNAME <\"$SEQ_DIR/head-name\"\n> \n> provided if these values are $IFS safe?\n\nAgain, my fault (as this was most likely copied from rebase -i).  All the \nfiles written to $DOTEST in rebase -i should be $IFS safe.\n\n> > +\tcase $HEADNAME in\n> > +\trefs/*)\n> > +\t\tgit symbolic-ref HEAD \"$HEADNAME\"\n> > +\t\t;;\n> > +\tesac &&\n> > +\toutput git reset --hard \"$HEAD\"\n> > +}\n> > +\n> > +has_action () {\n> > +\tgrep '^[^#]' \"$1\" >/dev/null\n> > +}\n> > +\n> > +# Check if text file $1 contains a commit message\n> > +has_message () {\n> > +\ttest -n \"$(sed -n -e '/^Signed-off-by:/d;/^[^#]/p' <\"$1\")\"\n> > +}\n> \n> Makes one wonder if we would want to special case other kinds like\n> \"Acked-by:\" as well...\n\nI think this just mimicks \"git commit\".\n\n> > +# Usage: pick_one (cherry-pick|revert) [-*|--edit] sha1\n> > +pick_one () {\n> > +\twhat=\"$1\"\n> > +\t# we just assume that this is either cherry-pick or revert\n> > +\tshift\n> > +\n> > +\t# check for fast-forward if no options are given\n> > +\tif expr \"x$1\" : 'x[^-]' >/dev/null\n> > +\tthen\n> > +\t\ttest \"$(git rev-parse --verify \"$1^\")\" = \\\n> > +\t\t\t\"$(git rev-parse --verify HEAD)\" &&\n> > +\t\t\toutput git reset --hard \"$1\" &&\n> > +\t\t\treturn\n> > +\tfi\n> > +\ttest \"$1\" != '--edit' -a \"$what\" = 'revert' &&\n> > +\t\twhat='revert --no-edit'\n> \n> This looks somewhat wrong.\n> \n> When the history looks like ---A---B and we are at A, cherry-picking B can\n> be optimized to just advancing to B, but that optimization has a slight\n> difference (or two) in the semantics.\n> \n>  (1) The committer information would not record the user and time of the\n>      sequencer operation, which actually may be a good thing.\n\nThis is debatable.  But I think you are correct, for all the same reasons \nwhy a merge can result in a fast-forward.\n\n>  (2) When $what is revert, this codepath shouldn't be exercised, should \n>  it?\n\nYes.\n\n>  (3) If B is a merge, even if $what is pick, this codepath shouldn't be\n>      exercised, should it?\n\nI think it should, again for the same reason why a merge can result in a \nfast-forward.\n\n> > +make_squash_message () {\n> > +\tif test -f \"$squash_msg\"\n> > +\tthen\n> > +\t\tcount=$(($(sed -n -e 's/^# This is [^0-9]*\\([1-9][0-9]*\\).*/\\1/p' \\\n> > +\t\t\t<\"$squash_msg\" | sed -n -e '$p')+1))\n> > +\t\techo \"# This is a combination of $count commits.\"\n> > +\t\tsed -e '1d' -e '2,/^./{\n> > +\t\t\t/^$/d\n> > +\t\t}' <\"$squash_msg\"\n> > +\telse\n> > +\t\tcount=2\n> > +\t\techo '# This is a combination of 2 commits.'\n> > +\t\techo '# The first commit message is:'\n> > +\t\techo\n> > +\t\tcommit_message HEAD\n> > +\tfi\n> > +\techo\n> > +\techo \"# This is the $(nth_string \"$count\") commit message:\"\n> > +\techo\n> > +\tcommit_message \"$1\"\n> > +}\n> > +\n> > +make_squash_message_multiple () {\n> > +\techo '# This is a dummy to get the 0.' >\"$squash_msg\"\n> > +\tfor cur_sha1 in $(git rev-list --reverse \"$sha1..HEAD\")\n> > +\tdo\n> > +\t\tmake_squash_message \"$cur_sha1\" >\"$MSG\"\n> > +\t\tcp \"$MSG\" \"$squash_msg\"\n> > +\tdone\n> > +}\n> \n> Hmm, I know this is how rebase-i is written, but we should be able to do\n> better than writing and flipping temporary times N times, shouldn't we?\n\nRight, again my fault.\n\n> > +peek_next_command () {\n> > +\tsed -n -e '1s/ .*$//p' <\"$TODO\"\n> > +}\n> \n> ... which could respond \"the next command is '#' (comment)\", so we are\n> actively counting a comment as a step here.  Does this contradict with the\n> mental note we made earlier, and if so, does the discrepancy hurt us\n> somewhere in this program?\n\nYes, this is wrong.  it must be\n\n\tsed -n -e '/^#/d' -e '1s .*$//p' < \"$TODO\"\n\n> > +strategy_check () {\n> > +\tcase \"$1\" in\n> > +\tresolve|recursive|octopus|ours|subtree|theirs)\n> > +\t\treturn\n> > +\t\t;;\n> > +\tesac\n> > +\ttodo_warn \"Strategy '$1' not known.\"\n> > +}\n> \n> Hmm.  Do we need to maintain list of available strategies here and then in\n> git-merge separately?\n\nI'd not check in sequencer for the strategy.  Especially given that we \nwant to support user-written strategies in the future.\n\nCiao,\nDscho\n"},{"id":"82126","messageId":"m3d4lvf70w.fsf@localhost.localdomain","threadId":"14239","inReplyTo":"1214879914-17866-2-git-send-email-s-beyer@gmx.net","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-07-03T13:10:12Z","receivedAt":"2008-07-03T13:10:12Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Stephan Beyer <s-beyer@gmx.net> writes:\n\n> +# Generate message, patch and author script files\n> +make_patch () {\n> +\tparent_sha1=$(git rev-parse --verify \"$1\"^) ||\n> +\t\tdie \"Cannot get patch for $1^\"\n> +\tgit diff-tree -p \"$parent_sha1..$1\" >\"$PATCH\"\n\nFirst, let's not perpetuate _convenience_ calling convention of \"A..B\"\nof git-diff* family, but use \"A B\" to set _endpoints_.\n\nSecond, with \"A B\" convention you can fairly easy deal with root\ncommit, changing the code to the fragment below:\n\n+# Generate message, patch and author script files\n+make_patch () {\n+\tparent_sha1=$(git rev-parse --verify \"$1\"^) ||\n+\t\techo '--root'\n+\tgit diff-tree -p \"$parent_sha1\" \"$1\" >\"$PATCH\"\n\n\nBTW. what is best way of checking if given revision is parent-less?\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"82157","messageId":"20080703210950.GC6677@leksak.fem-net","threadId":"14239","inReplyTo":"alpine.DEB.1.00.0807031142540.9925@racer","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-03T21:09:50Z","receivedAt":"2008-07-03T21:09:50Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn Thu, Jul 03, 2008 at 12:03:49PM +0100, Johannes Schindelin wrote:\n> Hi,\n> \n> On Wed, 2 Jul 2008, Junio C Hamano wrote:\n> > Stephan Beyer <s-beyer@gmx.net> writes:\n> > \n> > > git sequencer is planned as a backend for user scripts\n> > > that execute a sequence of git instructions and perhaps\n> > > need manual intervention, for example git-rebase or git-am.\n> > \n> > ...\n> > > +output () {\n> > > +\tcase \"$VERBOSE\" in\n> > > +\t0)\n> > > +\t\t\"$@\" >/dev/null\n> > > +\t\t;;\n> > > +\t1)\n> > > +\t\toutput=$(\"$@\" 2>&1 )\n> > > +\t\tstatus=$?\n> > > +\t\ttest $status -ne 0 && printf '%s\\n' \"$output\"\n> > > +\t\treturn $status\n> > > +\t\t;;\n> > > +\t2)\n> > > +\t\t\"$@\"\n> > > +\t\t;;\n> > > +\tesac\n> > > +}\n> > \n> > Perhaps misnamed?  This feels more like \"do\" or \"perform\" or \"run\".\n> \n> My fault.  I like \"perform\".\n\nRight, the \"output\" name puts a wrong behavior in mind.\n\"perform\" (or \"do\" or \"run\") won't exactly say that this function\n\"adjusts\" the output somehow, but I'm nonetheless fine with taking\n\"perform\".\n\n(I inline-attach patches so that you can incrementally review what I did\nwith your feedback.)\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -75,7 +75,7 @@ quit () {\n \texit 0\n }\n \n-output () {\n+perform () {\n \tcase \"$VERBOSE\" in\n \t0)\n \t\t\"$@\" >/dev/null\n@@ -165,7 +165,7 @@ restore () {\n \t\tgit symbolic-ref HEAD \"$HEADNAME\"\n \t\t;;\n \tesac &&\n-\toutput git reset --hard \"$HEAD\"\n+\tperform git reset --hard \"$HEAD\"\n }\n \n has_action () {\n@@ -208,14 +208,14 @@ pick_one () {\n \tthen\n \t\ttest \"$(git rev-parse --verify \"$1^\")\" = \\\n \t\t\t\"$(git rev-parse --verify HEAD)\" &&\n-\t\t\toutput git reset --hard \"$1\" &&\n+\t\t\tperform git reset --hard \"$1\" &&\n \t\t\treturn\n \tfi\n \ttest \"$1\" != '--edit' -a \"$what\" = 'revert' &&\n \t\twhat='revert --no-edit'\n \ttest -n \"$SIGNOFF\" &&\n \t\twhat=\"$what -s\"\n-\t$use_output git $what \"$@\"\n+\t$use_perform git $what \"$@\"\n }\n \n nth_string () {\n@@ -945,15 +945,15 @@ insn_pick () {\n \t# Be kind to users and ignore --mainline=1 on non-merge commits\n \ttest -n \"$mainline\" -a 2 -gt $(count_parents \"$sha1\") && mainline=\n \n-\tuse_output=\n+\tuse_perform=\n \ttest -n \"$edit_msg\" ||\n-\t\tuse_output=output\n+\t\tuse_perform=perform\n \n \tpick_one \"$op\" $edit_msg $mainline $sha1 ||\n \t\tdie_with_patch $sha1 \"Could not apply $sha1\"\n \n \ttest -n \"$EDIT\" ||\n-\t\tuse_output=output\n+\t\tuse_perform=perform\n \n \tget_current_author\n \tsignoff=\n@@ -961,18 +961,18 @@ insn_pick () {\n \tif test -n \"$AUTHOR\" -a -n \"$MESSAGE\"\n \tthen\n \t\t# this is just because we only want to do ONE amending commit\n-\t\t$use_output git commit --amend $EDIT $signoff --no-verify \\\n+\t\t$use_perform git commit --amend $EDIT $signoff --no-verify \\\n \t\t\t--author \"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\" \\\n \t\t\t--message=\"$MESSAGE\"\n \telse\n \t\t# correct author if AUTHOR is set\n \t\ttest -n \"$AUTHOR\" &&\n-\t\t\t$use_output git commit --amend $EDIT --no-verify -C HEAD \\\n+\t\t\t$use_perform git commit --amend $EDIT --no-verify -C HEAD \\\n \t\t\t\t--author \"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\"\n \t\t# XXX: a git-cherry-pick --author could be nicer here\n \t\t# correct commit message if MESSAGE is set\n \t\ttest -n \"$MESSAGE\" &&\n-\t\t\t$use_output git commit --amend $EDIT $signoff --no-verify \\\n+\t\t\t$use_perform git commit --amend $EDIT $signoff --no-verify \\\n \t\t\t\t-C HEAD --message=\"$MESSAGE\"\n \tfi\n \n@@ -1128,12 +1128,12 @@ insn_squash () {\n \tcase \"$(peek_next_command)\" in\n \tsquash)\n \t\tedit_commit=\n-\t\tuse_output=output\n+\t\tuse_perform=perform\n \t\tcp \"$MSG\" \"$squash_msg\"\n \t\t;;\n \t*)\n \t\tedit_commit=-e\n-\t\tuse_output=\n+\t\tuse_perform=\n \t\trm -f \"$squash_msg\" || exit\n \t\t;;\n \tesac\n@@ -1157,9 +1157,9 @@ insn_squash () {\n \tfailed=\n \tif test -n \"$from\"\n \tthen\n-\t\toutput git reset --soft \"$sha1\"\n+\t\tperform git reset --soft \"$sha1\"\n \telse\n-\t\toutput git reset --soft HEAD^\n+\t\tperform git reset --soft HEAD^\n \n \t\tpick_one cherry-pick -n \"$sha1\" || failed=t\n \tfi\n@@ -1169,7 +1169,7 @@ insn_squash () {\n \tif test -z \"$failed\"\n \tthen\n \t\t# This is like --amend, but with a different message\n-\t\twith_author $use_output git commit --no-verify \\\n+\t\twith_author $use_perform git commit --no-verify \\\n \t\t\t-F \"$MSG\" $edit_commit || failed=t\n \telse\n \t\tcp \"$MSG\" \"$GIT_DIR/MERGE_MSG\"\n@@ -1320,13 +1320,13 @@ insn_merge () {\n \tfi\n \n \tmark_action_done\n-\tif ! with_author output git merge $strategy -m junk $new_parents\n+\tif ! with_author perform git merge $strategy -m junk $new_parents\n \tthen\n \t\tgit rerere\n \t\tcat \"$MSG\" >\"$GIT_DIR/MERGE_MSG\"\n \t\tdie_to_continue 'Error merging'\n \tfi\n-\twith_author output git commit --amend -F \"$MSG\" --no-verify\n+\twith_author perform git commit --amend -F \"$MSG\" --no-verify\n \treturn 0\n }\n \n@@ -1352,7 +1352,7 @@ insn_reset () {\n \tcomment_for_reflog reset\n \n \tmark_action_done\n-\toutput git reset --hard \"$(mark_to_commit \"$1\")\"\n+\tperform git reset --hard \"$(mark_to_commit \"$1\")\"\n }\n \n \n@@ -1375,7 +1375,7 @@ insn_ref () {\n \tcomment_for_reflog ref\n \n \tmark_action_done\n-\toutput git update-ref \"$1\" HEAD\n+\tperform git update-ref \"$1\" HEAD\n }\n \n \n@@ -1547,10 +1547,10 @@ do_startup () {\n \t\tthen\n \t\t\tONTO=\"refs/heads/${ONTO##*/}\"\n \t\t\techo \"$ONTO\" >\"$SEQ_DIR/onto\"\n-\t\t\toutput git checkout \"$(git rev-parse \"$ONTO\")\" ||\n+\t\t\tperform git checkout \"$(git rev-parse \"$ONTO\")\" ||\n \t\t\t\tdie_abort \"Could not checkout branch $ONTO\"\n \t\telse\n-\t\t\toutput git checkout \"$ONTO\" ||\n+\t\t\tperform git checkout \"$ONTO\" ||\n \t\t\t\tdie_abort \"Could not checkout commit $ONTO\"\n \t\t\tONTO=\n \t\tfi\n@@ -1653,7 +1653,7 @@ Fix with git sequencer --edit or abort with $(print_caller --abort).\"\n \tcomment_for_reflog skip\n \tgit rerere clear\n \n-\toutput git reset --hard \"$(cat \"$SEQ_DIR/skiphead\")\" &&\n+\tperform git reset --hard \"$(cat \"$SEQ_DIR/skiphead\")\" &&\n \trm -f \"$WHY_FILE\" &&\n \techo '# SKIPPED the last instruction' >>\"$DONE\" &&\n \t\texecute_rest\n###\n\nOn Wed, Jul 02, 2008 at 06:45:06PM -0700, Junio C Hamano wrote:\n> > +LAST_COUNT=\n> > +mark_action_done () {\n> > +\tsed -e 1q <\"$TODO\" >>\"$DONE\"\n> > +\tsed -e 1d <\"$TODO\" >\"$TODO.new\"\n> > +\tmv -f \"$TODO.new\" \"$TODO\"\n> > +\tif test \"$VERBOSE\" -gt 0\n> > +\tthen\n> > +\t\tcount=$(grep -c '^[^#]' <\"$DONE\")\n> > +\t\ttotal=$(expr \"$count\" + \"$(grep -c '^[^#]' <\"$TODO\")\")\n> \n> Here we are not counting lines that are comments as insns (I am not\n> complaining; just making a mental note).\n\nAdd to your note, that empty lines are also skipped, because at least\none character (which is not #) must be there.\nAnd add to your note, that leading whitespace is not ignored on that\nchecks, which can lead to wrong numbers, but: (quoting Dscho)\n> \"count\" and \"total\" are only used for the progress output\n\n(The builtin handles that better because it just does proper parsing\nand not such hacks.)\n\nJunio C Hamano wrote:\n> > +\t\tif test \"$LAST_COUNT\" != \"$count\"\n> > +\t\tthen\n> > +\t\t\tLAST_COUNT=\"$count\"\n> > +\t\t\ttest \"$VERBOSE\" -lt 1 ||\n> > +\t\t\t\tprintf 'Sequencing (%d/%d)\\r' \"$count\" \"$total\"\n> > +\t\t\ttest \"$VERBOSE\" -lt 2 || echo\n> > +\t\tfi\n> > +\tfi\n> > +}\n> > +\n> > +# Generate message, patch and author script files\n> > +make_patch () {\n> > +\tparent_sha1=$(git rev-parse --verify \"$1\"^) ||\n> > +\t\tdie \"Cannot get patch for $1^\"\n> > +\tgit diff-tree -p \"$parent_sha1..$1\" >\"$PATCH\"\n> \n> Could there be a case where we need/want to deal with a root commit\n> without parents?\n\nYes, and this is not handled correctly.\n\nI've taken Jakub's idea:\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -139,9 +139,9 @@ mark_action_done () {\n \n # Generate message, patch and author script files\n make_patch () {\n-\tparent_sha1=$(git rev-parse --verify \"$1\"^) ||\n-\t\tdie \"Cannot get patch for $1^\"\n-\tgit diff-tree -p \"$parent_sha1..$1\" >\"$PATCH\"\n+\tparent_sha1=$(git rev-parse --verify \"$1^\" 2>/dev/null ||\n+\t\techo '--root')\n+\tgit diff-tree -p \"$parent_sha1\" \"$1\" >\"$PATCH\"\n \ttest -f \"$MSG\" ||\n \t\tcommit_message \"$1\" >\"$MSG\"\n \ttest -f \"$AUTHOR_SCRIPT\" ||\n###\n\nBtw, another root commit problem is btw that it's not possible\nto cherry-pick root commits.\n\nJunio C Hamano wrote:\n> > +\ttest -f \"$MSG\" ||\n> > +\t\tcommit_message \"$1\" >\"$MSG\"\n> > +\ttest -f \"$AUTHOR_SCRIPT\" ||\n> > +\t\tget_author_ident_from_commit \"$1\" >\"$AUTHOR_SCRIPT\"\n> > +}\n> > +\n> > +# Generate a patch and die with \"conflict\" status code\n> > +die_with_patch () {\n> > +\tmake_patch \"$1\"\n> > +\tgit rerere\n> > +\tdie_to_continue \"$2\"\n> > +}\n> > +\n> > +restore () {\n> > +\tgit rerere clear\n> > +\n> > +\tHEADNAME=$(cat \"$SEQ_DIR/head-name\")\n> > +\tHEAD=$(cat \"$SEQ_DIR/head\")\n> \n> Perhaps\n> \n> \tread HEADNAME <\"$SEQ_DIR/head-name\"\n> \n> provided if these values are $IFS safe?\n\nThey are IFS-safe. I don't really have an opinion if\n\tread FOO <foo\nis better than\n\tFOO=$(cat foo)\nor vice versa, so I have no problem to change this.\n\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -158,8 +158,8 @@ die_with_patch () {\n restore () {\n \tgit rerere clear\n \n-\tHEADNAME=$(cat \"$SEQ_DIR/head-name\")\n-\tHEAD=$(cat \"$SEQ_DIR/head\")\n+\tread HEADNAME <\"$SEQ_DIR/head-name\"\n+\tread HEAD <\"$SEQ_DIR/head\"\n \tcase $HEADNAME in\n \trefs/*)\n \t\tgit symbolic-ref HEAD \"$HEADNAME\"\n@@ -1496,9 +1496,10 @@ prepare_editable_todo () {\n }\n \n get_saved_options () {\n-\tVERBOSE=$(cat \"$SEQ_DIR/verbose\")\n-\tONTO=$(cat \"$SEQ_DIR/onto\")\n-\tWHY=$(cat \"$WHY_FILE\" 2>/dev/null)\n+\tread VERBOSE <\"$SEQ_DIR/verbose\"\n+\tread ONTO <\"$SEQ_DIR/onto\"\n+\ttest -f \"$WHY_FILE\" &&\n+\t\tread WHY <\"$WHY_FILE\"\n \treturn 0\n }\n \n###\n\nJohannes Schindelin wrote:\n> > > +# Usage: pick_one (cherry-pick|revert) [-*|--edit] sha1\n> > > +pick_one () {\n> > > +\twhat=\"$1\"\n> > > +\t# we just assume that this is either cherry-pick or revert\n> > > +\tshift\n> > > +\n> > > +\t# check for fast-forward if no options are given\n> > > +\tif expr \"x$1\" : 'x[^-]' >/dev/null\n> > > +\tthen\n> > > +\t\ttest \"$(git rev-parse --verify \"$1^\")\" = \\\n> > > +\t\t\t\"$(git rev-parse --verify HEAD)\" &&\n> > > +\t\t\toutput git reset --hard \"$1\" &&\n> > > +\t\t\treturn\n> > > +\tfi\n> > > +\ttest \"$1\" != '--edit' -a \"$what\" = 'revert' &&\n> > > +\t\twhat='revert --no-edit'\n> > \n> > This looks somewhat wrong.\n> > \n> > When the history looks like ---A---B and we are at A, cherry-picking B can\n> > be optimized to just advancing to B, but that optimization has a slight\n> > difference (or two) in the semantics.\n> > \n> >  (1) The committer information would not record the user and time of the\n> >      sequencer operation, which actually may be a good thing.\n> \n> This is debatable.  But I think you are correct, for all the same reasons \n> why a merge can result in a fast-forward.\n\nDscho, you mean me by referring to 'you' here, right?\nOtherwise I'm a bit confused: \"For the same reasons why a merge can result\nin a fast-forward we should not do fast forward here\" ;-)\n\nI think the ff is more useful than real picking and I think the rebase-i\ntest suite even has a test case for this.\n(Checked: \"* FAIL 17: merge redoes merges\" if it is removed, so it's\nimplicitly checked for redone merges.)\n\n> >  (2) When $what is revert, this codepath shouldn't be exercised, should \n> >  it?\n> \n> Yes.\n\nI haven't done a check intentionally, but there was a stupid thinko.\nSo you're right.\n\nBut: this will only be a bug if the commit that _comes next in the\noriginal history_ is to be reverted.  This is usually user-nonsense\n(I can't imagine a useful application for that), but nonetheless a\nuser can try it for fun and such a case is not worth a sanity check.\nSo it's perhaps good to add a test here and just do the revert (and no\nff) as the user requests.\n\n> >  (3) If B is a merge, even if $what is pick, this codepath shouldn't be\n> >      exercised, should it?\n> \n> I think it should, again for the same reason why a merge can result in a \n> fast-forward.\n\nRight.\n\nJunio C Hamano wrote:\n> As to the syntax I tend to prefer\n> \n> \tcase \"$1\" in\n>         -*)\t... do option thing ... ;;\n>         *)\t... do other thing... ;;\n>         esac\n\nChristian has mentioned this, but I didn't listen to him ;)\nBecause I think, if you put the cases, the do_thing and the ;;\non separate lines,\n1. it is just consistent compared to the cases where you\n   do several things ... you don't do them on one line and\n   you put the ;; on an extra line\n2. the diffs will look better on extensions\n\n> So how about...\n> \n> \tcase \"$what,$1\" in\n>         revert,--edit)\n>         \twhat='revert --no-edit' ;;\n>         revert,* | cherry-pick,-* )\n>         \t;;\n>         *)\n> \t\tif ! git rev-parse --verify \"$1^2\" &&\n> \t                test \"$(git rev-parse --verify \"$1^\") = \\\n>                 \t\"$(git rev-parse --verify HEAD)\"\n> \t\tthen\n>                 \toutput git reset --hard \"$1\"\n> \t\t\treturn\n> \t\tfi\n> \t\t;;\n> \tesac\n\nI've done this:\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -200,19 +200,25 @@ with_author () {\n # Usage: pick_one (cherry-pick|revert) [-*|--edit] sha1\n pick_one () {\n \twhat=\"$1\"\n-\t# we just assume that this is either cherry-pick or revert\n \tshift\n \n-\t# check for fast-forward if no options are given\n-\tif expr \"x$1\" : 'x[^-]' >/dev/null\n-\tthen\n-\t\ttest \"$(git rev-parse --verify \"$1^\")\" = \\\n-\t\t\t\"$(git rev-parse --verify HEAD)\" &&\n-\t\t\tperform git reset --hard \"$1\" &&\n+\tcase \"$what,$1\" in\n+\trevert,*)\n+\t\ttest \"$1\" != '--edit' &&\n+\t\t\twhat='revert --no-edit'\n+\t\t;;\n+\tcherry-pick,-*)\n+\t\t;;\n+\tcherry-pick,*)\n+\t\t# fast forward\n+\t\tif test \"$(git rev-parse --verify \"$1^\")\" = \\\n+\t\t\t\"$(git rev-parse --verify HEAD)\"\n+\t\tthen\n+\t\t\tperform git reset --hard \"$1\"\n \t\t\treturn\n-\tfi\n-\ttest \"$1\" != '--edit' -a \"$what\" = 'revert' &&\n-\t\twhat='revert --no-edit'\n+\t\tfi\n+\t\t;;\n+\tesac\n \ttest -n \"$SIGNOFF\" &&\n \t\twhat=\"$what -s\"\n \t$use_perform git $what \"$@\"\n###\n\nJohannes Schindelin wrote:\n> > > +make_squash_message () {\n> > > +\tif test -f \"$squash_msg\"\n> > > +\tthen\n> > > +\t\tcount=$(($(sed -n -e 's/^# This is [^0-9]*\\([1-9][0-9]*\\).*/\\1/p' \\\n> > > +\t\t\t<\"$squash_msg\" | sed -n -e '$p')+1))\n> > > +\t\techo \"# This is a combination of $count commits.\"\n> > > +\t\tsed -e '1d' -e '2,/^./{\n> > > +\t\t\t/^$/d\n> > > +\t\t}' <\"$squash_msg\"\n> > > +\telse\n> > > +\t\tcount=2\n> > > +\t\techo '# This is a combination of 2 commits.'\n> > > +\t\techo '# The first commit message is:'\n> > > +\t\techo\n> > > +\t\tcommit_message HEAD\n> > > +\tfi\n> > > +\techo\n> > > +\techo \"# This is the $(nth_string \"$count\") commit message:\"\n> > > +\techo\n> > > +\tcommit_message \"$1\"\n> > > +}\n> > > +\n> > > +make_squash_message_multiple () {\n> > > +\techo '# This is a dummy to get the 0.' >\"$squash_msg\"\n> > > +\tfor cur_sha1 in $(git rev-list --reverse \"$sha1..HEAD\")\n> > > +\tdo\n> > > +\t\tmake_squash_message \"$cur_sha1\" >\"$MSG\"\n> > > +\t\tcp \"$MSG\" \"$squash_msg\"\n> > > +\tdone\n> > > +}\n> > \n> > Hmm, I know this is how rebase-i is written, but we should be able to do\n> > better than writing and flipping temporary times N times, shouldn't we?\n> \n> Right, again my fault.\n\nNo, not your fault.\nI think Junio is referring to make_squash_message_multiple which is for\n\tsquash --from <mark>\nand just calls your make_squash_message several times.\n\nWhen I did this, I knew that this is not most efficient, but I had in\nmind: this is just a prototype. The builtin will solve this in a\ndifferent way.\n\nNonetheless, purely tested:\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -264,11 +264,26 @@ make_squash_message () {\n }\n \n make_squash_message_multiple () {\n-\techo '# This is a dummy to get the 0.' >\"$squash_msg\"\n-\tfor cur_sha1 in $(git rev-list --reverse \"$sha1..HEAD\")\n+\trevlist=$(git rev-list --reverse \"$sha1..HEAD\")\n+\tcount=$(echo \"$revlist\" | wc -l)\n+\tsquash_i=0\n+\techo \"# This is a combination of $count commits.\"\n+\tfor cur_sha1 in $revlist\n \tdo\n-\t\tmake_squash_message \"$cur_sha1\" >\"$MSG\"\n-\t\tcp \"$MSG\" \"$squash_msg\"\n+\t\tsquash_i=$(($squash_i+1))\n+\t\tif test -f \"$squash_msg\"\n+\t\tthen\n+\t\t\tcount=$(($count + $(sed -n -e \\\n+\t\t\t\t's/^# This is [^0-9]*\\([1-9][0-9]*\\).*/\\1/p' \\\n+\t\t\t\t<\"$squash_msg\" | sed -n -e '$p')+1))\n+\t\t\tsed -e '1d' -e '2,/^./{\n+\t\t\t\t/^$/d\n+\t\t\t}' <\"$squash_msg\"\n+\t\tfi\n+\t\techo\n+\t\techo \"# This is the $(nth_string \"$squash_i\") commit message:\"\n+\t\techo\n+\t\tcommit_message \"$cur_sha1\"\n \tdone\n }\n \n@@ -1128,7 +1143,7 @@ insn_squash () {\n \telse\n \t\tif test -n \"$from\"\n \t\tthen\n-\t\t\tmake_squash_message_multiple \"$sha1\"\n+\t\t\tmake_squash_message_multiple \"$sha1\" >\"$MSG\"\n \t\telse\n \t\t\tmake_squash_message \"$sha1\" >\"$MSG\"\n \t\tfi\n###\n\nJohannes Schindelin wrote:\n> > > +peek_next_command () {\n> > > +\tsed -n -e '1s/ .*$//p' <\"$TODO\"\n> > > +}\n> > \n> > ... which could respond \"the next command is '#' (comment)\", so we are\n> > actively counting a comment as a step here.  Does this contradict with the\n> > mental note we made earlier, and if so, does the discrepancy hurt us\n> > somewhere in this program?\n\nYes it does hurt ;-)\n\n> Yes, this is wrong.  it must be\n> \n> \tsed -n -e '/^#/d' -e '1s .*$//p' < \"$TODO\"\n\nThanks ;)\n\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -273,7 +273,7 @@ make_squash_message_multiple () {\n }\n \n peek_next_command () {\n-\tsed -n -e '1s/ .*$//p' <\"$TODO\"\n+\tsed -n -e '/^#/d' -e '1s/ .*$//p' <\"$TODO\"\n }\n \n # If $1 is a mark, make a ref from it; otherwise keep it.\n###\n\nJunio C Hamano wrote:\n> > +# If $1 is a mark, make a ref from it; otherwise keep it\n> > +mark_to_ref () {\n> > +\targ=\"$1\"\n> > +\tref=$(expr \"x$arg\" : 'x:0*\\([0-9][0-9]*\\)$')\n> \n> You might want to leave comments to describe constraints that led to this\n> slightly awkward regexp:\n> \n>  * :0 is allowed\n>  * :01 is the same as :1\n\nRight.\n\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -270,7 +270,10 @@ peek_next_command () {\n \tsed -n -e '1s/ .*$//p' <\"$TODO\"\n }\n \n-# If $1 is a mark, make a ref from it; otherwise keep it\n+# If $1 is a mark, make a ref from it; otherwise keep it.\n+# Note on marks:\n+#  * :0 is allowed\n+#  * :01 is the same as :1\n mark_to_ref () {\n \targ=\"$1\"\n \tref=$(expr \"x$arg\" : 'x:0*\\([0-9][0-9]*\\)$')\n###\n\nJunio C Hamano wrote:\n> > +strategy_check () {\n> > +\tcase \"$1\" in\n> > +\tresolve|recursive|octopus|ours|subtree|theirs)\n> > +\t\treturn\n> > +\t\t;;\n> > +\tesac\n> > +\ttodo_warn \"Strategy '$1' not known.\"\n> > +}\n> \n> Hmm.  Do we need to maintain list of available strategies here and then in\n> git-merge separately?\n\nNo, this is potentially-error-prone at large.\nBut I want a check for this, so I'd vote for a\n\t--list-strategies\nfeature in the builtin-merge.\n(Before writing the quoted code, I was looking for such a feature, but\nhaven't found. But since builtin-merge is in work I didn't want send\npatches on git-merge.sh)\n\nJohannes Schindelin wrote:\n> I'd not check in sequencer for the strategy.  Especially given that we \n> want to support user-written strategies in the future.\n\nI don't know how this is planned to look like, but perhaps --list-strategies\nmay make sense here, too.\nAlso, the shell completion scripts could use that.\n\nJunio C Hamano wrote:\n> > +### Author script functions\n> > +\n> > +clean_author_script () {\n> > +\tcat \"$ORIG_AUTHOR_SCRIPT\" >\"$AUTHOR_SCRIPT\"\n> > +}\n> > +\n> > +# Take \"Name <e-mail>\" in stdin and outputs author script\n> > +make_author_script_from_string () {\n> > +\tsed -e 's/^\\(.*\\) <\\(.*\\)>.*$/GIT_AUTHOR_NAME=\"\\1\"\\\n> > +GIT_AUTHOR_EMAIL=\"\\2\"\\\n> > +GIT_AUTHOR_DATE=/'\n> > +}\n> \n> If you are going to \".\"-source or eval the output from this, you would\n> need to quote the values a lot more robustly, wouldn't you?  Is this safe\n> against shell metacharacters in names, mails and/or space between unixtime\n> and the timezone information?\n\nTime is set empty here.\nIt is not save according to shell metacharacters in name or e-mail and I\nknew that when writing.\nOf course, a\n\tFirst \"nick\" Sure\nauthor will get problems here. ;-)\nAnd as long as nobody is named $(rm -rf \"$HOME\")  [1], I thought this is\nsufficient for the prototype.\n\nBut...\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -520,7 +520,7 @@ clean_author_script () {\n \n # Take \"Name <e-mail>\" in stdin and outputs author script\n make_author_script_from_string () {\n-\tsed -e 's/^\\(.*\\) <\\(.*\\)>.*$/GIT_AUTHOR_NAME=\"\\1\"\\\n+\tsed -e 's/[$\"\\\\]/\\\\&/g' -e 's/^\\(.*\\) <\\(.*\\)>.*$/GIT_AUTHOR_NAME=\"\\1\"\\\n GIT_AUTHOR_EMAIL=\"\\2\"\\\n GIT_AUTHOR_DATE=/'\n }\n@@ -779,7 +779,7 @@ insn_patch () {\n \t\n \tif test -z \"$AUTHOR\"\n \tthen\n-\t\tsed -n -e '\n+\t\tsed -e 's/[$\"\\\\]/\\\\&/g' -n -e '\n \t\t\ts/^Author: \\(.*\\)$/GIT_AUTHOR_NAME=\"\\1\"/p;\n \t\t\ts/^Email: \\(.*\\)$/GIT_AUTHOR_EMAIL=\"\\1\"/p;\n \t\t\ts/^Date: \\(.*\\)$/GIT_AUTHOR_DATE=\"\\1\"/p\n###\n\nIs escaping $, \" and \\ enough?\n\n> > +\tif test -z \"$AUTHOR\"\n> > +\tthen\n> > +\t\tsed -n -e '\n> > +\t\t\ts/^Author: \\(.*\\)$/GIT_AUTHOR_NAME=\"\\1\"/p;\n> > +\t\t\ts/^Email: \\(.*\\)$/GIT_AUTHOR_EMAIL=\"\\1\"/p;\n> > +\t\t\ts/^Date: \\(.*\\)$/GIT_AUTHOR_DATE=\"\\1\"/p\n> > +\t\t' <\"$infofile\" >>\"$AUTHOR_SCRIPT\"\n> \n> The same comment on quoting applies here, I think.\n\nRight.\n\n> > +\tif test -n \"$failed\"\n> > +\tthen\n> > +\t\t# XXX: This is just a stupid hack:\n> > +\t\twith_author git apply $apply_opts --reject --index \"$PATCH\"\n> \n> Please don't do this without being asked, if you are planning to use this\n> in \"am\" when 3-way fallback was not asked.  It _may_ make sense to give an\n> option to the users to ask for .rej if they prefer to work that way better\n> than working with 3-way merge fallback, but doing this without being asked\n> is not acceptable.\n\nThe --reject was just a mind marker for that what I actually think is\nuseful and less annoying than the current behavior:\n\n> > +\t\tdie_to_continue 'Patch failed. See the .rej files.'\n> > +\t\t# XXX: We actually needed a git-apply flag that creates\n> > +\t\t# conflict markers and sets the DIFF_STATUS_UNMERGED flag.\n> \n> That is what -3way is all about, and this codepath is when the user did\n> not ask for it, isn't it?\n\nNow imagine you apply a patch that cannot be applied 100% cleanly and\nyou don't have the 3-way base in the repo. You know what happens?\nYes, the patch is completly rejected, because apply is atomic.\nAnd I think a git-apply option that results in a non-atomic behavior,\nthat creates conflict markers (and no .rej files), would be a great\nusability feature for the \"patch\" insn in sequencer.\nI'd even suggest to make that the default, but that's debatable.\n\nBtw, I removed the mind marker:\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -836,9 +836,7 @@ insn_patch () {\n \n \tif test -n \"$failed\"\n \tthen\n-\t\t# XXX: This is just a stupid hack:\n-\t\twith_author git apply $apply_opts --reject --index \"$PATCH\"\n-\t\tdie_to_continue 'Patch failed. See the .rej files.'\n+\t\tdie_to_continue 'Patch failed.'\n \t\t# XXX: We actually needed a git-apply flag that creates\n \t\t# conflict markers and sets the DIFF_STATUS_UNMERGED flag.\n \tfi\n###\n\n> > +# Check the \"pick\" instruction\n> > +check_pick () {\n> > +\trevert=\n> > +\tmainline=\n> > +\twhile test $# -gt 1\n> > +\tdo\n> > ...\n> > +\tdone\n> > +\n> > +\tif test -n \"$mainline\"\n> > +\tthen\n> > +\t\ttest -z \"$revert\" ||\n> > +\t\t\ttodo_error \"Cannot use $revert together with --mainline.\"\n> \n> Why not?  If you have this...\n> \n> \t---A---C---D\n>               /\n>           ---B\n> \n> and you are at D, you may want to undo the merge you made at C and go back\n> to either A or B, which essentially is same as cherry-picking diff between\n> C and D on top of either A or B.  Both are valid operations aren't they?\n\nJakub already asked. I told him, that git-revert doesn't know --mainline,\nbut it seems that this was wrong.  So:\n\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -879,13 +879,11 @@ $OPTIONS_GENERAL\n \n # Check the \"pick\" instruction\n check_pick () {\n-\trevert=\n \tmainline=\n \twhile test $# -gt 1\n \tdo\n \t\tcase \"$1\" in\n \t\t-R)\n-\t\t\trevert=\"$1\"\n \t\t\t;;\n \t\t--mainline)\n \t\t\tshift\n@@ -913,9 +911,6 @@ check_pick () {\n \n \tif test -n \"$mainline\"\n \tthen\n-\t\ttest -z \"$revert\" ||\n-\t\t\ttodo_error \"Cannot use $revert together with --mainline.\"\n-\n \t\tparents=$(count_parents \"$1\")\n \t\ttest \"$parents\" -lt \"$mainline\" &&\n \t\t\ttodo_error \"Commit has only $parents (less than $mainline) parents.\"\n###\n\nRegards and big thanks for the fast reply,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82158","messageId":"20080703211230.GD6677@leksak.fem-net","threadId":"14239","inReplyTo":"m3d4lvf70w.fsf@localhost.localdomain","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-03T21:12:30Z","receivedAt":"2008-07-03T21:12:30Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nfirst, thanks for the --root idea ;-)\n\n> BTW. what is best way of checking if given revision is parent-less?\n\nI think count the number of parents is quite sane.\n\nIn sequencer I have:\n\tcount_parents() {\n\t\tgit cat-file commit \"$1\" | sed -n -e '1,/^$/p' | grep -c '^parent'\n\t}\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82167","messageId":"7vlk0iy5we.fsf@gitster.siamese.dyndns.org","threadId":"14239","inReplyTo":"20080703210950.GC6677@leksak.fem-net","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-03T22:11:45Z","receivedAt":"2008-07-03T22:11:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephan Beyer <s-beyer@gmx.net> writes:\n\n> +\t\tsed -e 's/[$\"\\\\]/\\\\&/g' -n -e '\n>  \t\t\ts/^Author: \\(.*\\)$/GIT_AUTHOR_NAME=\"\\1\"/p;\n>  \t\t\ts/^Email: \\(.*\\)$/GIT_AUTHOR_EMAIL=\"\\1\"/p;\n>  \t\t\ts/^Date: \\(.*\\)$/GIT_AUTHOR_DATE=\"\\1\"/p\n> ###\n>\n> Is escaping $, \" and \\ enough?\n\nLook at how it is done in git-sh-setup get_author_ident_from_commit.\n\n>> > +\tif test -n \"$failed\"\n>> > +\tthen\n>> > +\t\t# XXX: This is just a stupid hack:\n>> > +\t\twith_author git apply $apply_opts --reject --index \"$PATCH\"\n>> \n>> Please don't do this without being asked, if you are planning to use this\n>> in \"am\" when 3-way fallback was not asked.  It _may_ make sense to give an\n>> option to the users to ask for .rej if they prefer to work that way better\n>> than working with 3-way merge fallback, but doing this without being asked\n>> is not acceptable.\n>\n> The --reject was just a mind marker for that what I actually think is\n> useful and less annoying than the current behavior:\n>\n>> > +\t\tdie_to_continue 'Patch failed. See the .rej files.'\n>> > +\t\t# XXX: We actually needed a git-apply flag that creates\n>> > +\t\t# conflict markers and sets the DIFF_STATUS_UNMERGED flag.\n>> \n>> That is what -3way is all about, and this codepath is when the user did\n>> not ask for it, isn't it?\n>\n> Now imagine you apply a patch that cannot be applied 100% cleanly and\n> you don't have the 3-way base in the repo. You know what happens?\n\nDo you think I don't?  You can check who invented 3way by running \"git\nlog\" or \"git blame\" on git-am.sh ;-)\n\nI think you misread my \"That is what -3way is all about\".  That remark is\nabout the comment you have about \"creates conflict markers\".  The conflict\nmarkers is only possible because we do 3-way merge when you ran \"am -3\".\nIf you do not have the base object but only a blob and an unapplicable\npatch, you cannot do \"here is our change since common ancestor, and here\nis their change the patch wants to make\" conflict markers, because you do\nnot have the common ancestor.\n\n> Yes, the patch is completly rejected, because apply is atomic.\n> And I think a git-apply option that results in a non-atomic behavior,\n> that creates conflict markers (and no .rej files), would be a great\n> usability feature for the \"patch\" insn in sequencer.\n\nYes, I think I already said in the message you are responding to that it\nmay make sense to have such an option (but at the same time we should\nremember that nobody asked to add --reject to \"git am\").\n"},{"id":"82168","messageId":"20080703223433.GE6677@leksak.fem-net","threadId":"14239","inReplyTo":"7vlk0iy5we.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-03T22:34:33Z","receivedAt":"2008-07-03T22:34:33Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"On Thu, Jul 03, 2008 at 03:11:45PM -0700, Junio C Hamano wrote:\n> Stephan Beyer <s-beyer@gmx.net> writes:\n> >> > +\t\tdie_to_continue 'Patch failed. See the .rej files.'\n> >> > +\t\t# XXX: We actually needed a git-apply flag that creates\n> >> > +\t\t# conflict markers and sets the DIFF_STATUS_UNMERGED flag.\n> >> \n> >> That is what -3way is all about, and this codepath is when the user did\n> >> not ask for it, isn't it?\n> >\n> > Now imagine you apply a patch that cannot be applied 100% cleanly and\n> > you don't have the 3-way base in the repo. You know what happens?\n> \n> Do you think I don't?  You can check who invented 3way by running \"git\n> log\" or \"git blame\" on git-am.sh ;-)\n\nI know you know.  The question was just rhetorical.\n\n> I think you misread my \"That is what -3way is all about\".  That remark is\n> about the comment you have about \"creates conflict markers\".  The conflict\n> markers is only possible because we do 3-way merge when you ran \"am -3\".\n> If you do not have the base object but only a blob and an unapplicable\n> patch, you cannot do \"here is our change since common ancestor, and here\n> is their change the patch wants to make\" conflict markers, because you do\n> not have the common ancestor.\n\nI didn't misread it.\nBut it is a wrong implication that you cannot do this when you do not have\na common ancestor.\nFor example: Even if no context matches (or no context exists), it is\npossible to add a conflict marker at the specified line. It can happen\nthat this will result in crap, but resolving some parts that just look\nwrong is easier than applying a patch 100% manually.\n\nI think I'm going to add such a git-apply option after GSoC, if nobody\ndoes this before.\n\n> > Yes, the patch is completly rejected, because apply is atomic.\n> > And I think a git-apply option that results in a non-atomic behavior,\n> > that creates conflict markers (and no .rej files), would be a great\n> > usability feature for the \"patch\" insn in sequencer.\n> \n> Yes, I think I already said in the message you are responding to that it\n> may make sense to have such an option (but at the same time we should\n> remember that nobody asked to add --reject to \"git am\").\n\nRight, so I removed it ;)\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82170","messageId":"7vbq1ey42w.fsf@gitster.siamese.dyndns.org","threadId":"14239","inReplyTo":"alpine.DEB.1.00.0807031142540.9925@racer","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-03T22:51:03Z","receivedAt":"2008-07-03T22:51:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n>> When the history looks like ---A---B and we are at A, cherry-picking B can\n>> be optimized to just advancing to B, but that optimization has a slight\n>> difference (or two) in the semantics.\n>> \n>>  (1) The committer information would not record the user and time of the\n>>      sequencer operation, which actually may be a good thing.\n>\n> This is debatable.  But I think you are correct, for all the same reasons \n> why a merge can result in a fast-forward.\n>\n>>  (2) When $what is revert, this codepath shouldn't be exercised, should \n>>  it?\n>\n> Yes.\n>\n>>  (3) If B is a merge, even if $what is pick, this codepath shouldn't be\n>>      exercised, should it?\n>\n> I think it should, again for the same reason why a merge can result in a \n> fast-forward.\n\nSorry, I disagree.  \"cherry-pick\" when this optimization is not applicable\nalways creates a single parent commit.  If the original history looks like:\n\n\tD---A---B---C\n               /\n              M\n\nand when you are cherry-picking B, the above logic would make the result a\nmerge if you happen to be at A but if you are working elsewhere (perhaps C\nor D, or \"rewritten A\") the result will become a single-parent commit.  I\ndo not see the justification behind such an unreliable/unpredictable\nresult, from the end-user's point of view.\n\nI like the check and avoidance of creating a commit that will anyway have\nthe same parent and the same tree as an _optimization_.  Making the result\nof \"cherry-pick B\" a merge or a non-merge however is not an optimization;\nit is changing semantics.\n"},{"id":"82173","messageId":"20080703233343.GF6677@leksak.fem-net","threadId":"14239","inReplyTo":"7vlk0iy5we.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-03T23:33:43Z","receivedAt":"2008-07-03T23:33:43Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi again,\n\n\nOn Thu, Jul 03, 2008 at 03:11:45PM -0700, Junio C Hamano wrote:\n> Stephan Beyer <s-beyer@gmx.net> writes:\n> > +\t\tsed -e 's/[$\"\\\\]/\\\\&/g' -n -e '\n> >  \t\t\ts/^Author: \\(.*\\)$/GIT_AUTHOR_NAME=\"\\1\"/p;\n> >  \t\t\ts/^Email: \\(.*\\)$/GIT_AUTHOR_EMAIL=\"\\1\"/p;\n> >  \t\t\ts/^Date: \\(.*\\)$/GIT_AUTHOR_DATE=\"\\1\"/p\n> > ###\n> >\n> > Is escaping $, \" and \\ enough?\n> \n> Look at how it is done in git-sh-setup get_author_ident_from_commit.\n\nYes, single quotes are the other variant and perhaps a little more\nrobust.\n\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -520,8 +520,9 @@ clean_author_script () {\n \n # Take \"Name <e-mail>\" in stdin and outputs author script\n make_author_script_from_string () {\n-\tsed -e 's/^\\(.*\\) <\\(.*\\)>.*$/GIT_AUTHOR_NAME=\"\\1\"\\\n-GIT_AUTHOR_EMAIL=\"\\2\"\\\n+\tsed -e \"s/'/'\"'\\\\'\"''/g\" \\\n+\t    -e 's/^\\(.*\\) <\\(.*\\)>.*$/GIT_AUTHOR_NAME='\\''\\1'\\''\\\n+GIT_AUTHOR_EMAIL='\\''\\2'\\''\\\n GIT_AUTHOR_DATE=/'\n }\n \n@@ -779,10 +780,10 @@ insn_patch () {\n \t\n \tif test -z \"$AUTHOR\"\n \tthen\n-\t\tsed -n -e '\n-\t\t\ts/^Author: \\(.*\\)$/GIT_AUTHOR_NAME=\"\\1\"/p;\n-\t\t\ts/^Email: \\(.*\\)$/GIT_AUTHOR_EMAIL=\"\\1\"/p;\n-\t\t\ts/^Date: \\(.*\\)$/GIT_AUTHOR_DATE=\"\\1\"/p\n+\t\tsed -e \"s/'/'\"'\\\\'\"''/g\" -n -e '\n+\t\t\ts/^Author: \\(.*\\)$/GIT_AUTHOR_NAME='\\''\\1'\\''/p;\n+\t\t\ts/^Email: \\(.*\\)$/GIT_AUTHOR_EMAIL='\\''\\1'\\''/p;\n+\t\t\ts/^Date: \\(.*\\)$/GIT_AUTHOR_DATE='\\''\\1'\\''/p\n \t\t' <\"$infofile\" >>\"$AUTHOR_SCRIPT\"\n \t\t# If sed's result is empty, we keep the original\n \t\t# author script by appending.\n###\n\nOn Thu, Jul 03, 2008 at 11:09:50PM +0200, Stephan Beyer wrote:\n> And as long as nobody is named $(rm -rf \"$HOME\")  [1], I thought this is\n> sufficient for the prototype.\n\nBtw, the [1] should have been a link to http://xkcd.com/327/\nJust if you're wondering ;-)\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82176","messageId":"alpine.DEB.1.00.0807040138090.2849@eeepc-johanness","threadId":"14239","inReplyTo":"20080703210950.GC6677@leksak.fem-net","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-07-03T23:53:21Z","receivedAt":"2008-07-03T23:53:21Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 3 Jul 2008, Stephan Beyer wrote:\n\n> On Thu, Jul 03, 2008 at 12:03:49PM +0100, Johannes Schindelin wrote:\n> \n> > On Wed, 2 Jul 2008, Junio C Hamano wrote:\n> > > Stephan Beyer <s-beyer@gmx.net> writes:\n> > > \n> > > > git sequencer is planned as a backend for user scripts that \n> > > > execute a sequence of git instructions and perhaps need manual \n> > > > intervention, for example git-rebase or git-am.\n> > > \n> > > ...\n> > > > +output () {\n> > > > +\tcase \"$VERBOSE\" in\n> > > > +\t0)\n> > > > +\t\t\"$@\" >/dev/null\n> > > > +\t\t;;\n> > > > +\t1)\n> > > > +\t\toutput=$(\"$@\" 2>&1 )\n> > > > +\t\tstatus=$?\n> > > > +\t\ttest $status -ne 0 && printf '%s\\n' \"$output\"\n> > > > +\t\treturn $status\n> > > > +\t\t;;\n> > > > +\t2)\n> > > > +\t\t\"$@\"\n> > > > +\t\t;;\n> > > > +\tesac\n> > > > +}\n> > > \n> > > Perhaps misnamed?  This feels more like \"do\" or \"perform\" or \"run\".\n> > \n> > My fault.  I like \"perform\".\n> \n> Right, the \"output\" name puts a wrong behavior in mind. \"perform\" (or \n> \"do\" or \"run\") won't exactly say that this function \"adjusts\" the output \n> somehow, but I'm nonetheless fine with taking \"perform\".\n\nActually, it does not even \"adjust\" the output.  It just performs the \naction, and _if_ there was an error and \"verbose\" was set to 1, it shows \nthe output.  If \"verbose\" was set to 2, it always shows the output.  \nOtherwise, the output is suppressed.\n\nSo, the use of the function really is in the output, but that is either \nshown or not shown, never modified.\n\n> Btw, another root commit problem is btw that it's not possible to \n> cherry-pick root commits.\n\nThat is a problem to be fixed in cherry-pick, not in sequencer.  Care to \ntake care of that?\n\n> Johannes Schindelin wrote:\n> > > > +# Usage: pick_one (cherry-pick|revert) [-*|--edit] sha1\n> > > > +pick_one () {\n> > > > +\twhat=\"$1\"\n> > > > +\t# we just assume that this is either cherry-pick or revert\n> > > > +\tshift\n> > > > +\n> > > > +\t# check for fast-forward if no options are given\n> > > > +\tif expr \"x$1\" : 'x[^-]' >/dev/null\n> > > > +\tthen\n> > > > +\t\ttest \"$(git rev-parse --verify \"$1^\")\" = \\\n> > > > +\t\t\t\"$(git rev-parse --verify HEAD)\" &&\n> > > > +\t\t\toutput git reset --hard \"$1\" &&\n> > > > +\t\t\treturn\n> > > > +\tfi\n> > > > +\ttest \"$1\" != '--edit' -a \"$what\" = 'revert' &&\n> > > > +\t\twhat='revert --no-edit'\n> > > \n> > > This looks somewhat wrong.\n> > > \n> > > When the history looks like ---A---B and we are at A, cherry-picking B can\n> > > be optimized to just advancing to B, but that optimization has a slight\n> > > difference (or two) in the semantics.\n> > > \n> > >  (1) The committer information would not record the user and time of the\n> > >      sequencer operation, which actually may be a good thing.\n> > \n> > This is debatable.  But I think you are correct, for all the same reasons \n> > why a merge can result in a fast-forward.\n> \n> Dscho, you mean me by referring to 'you' here, right?\n\nNope.\n\n> Otherwise I'm a bit confused: \"For the same reasons why a merge can \n> result in a fast-forward we should not do fast forward here\" ;-)\n\nWhat I meant: there is no use here to redo it.  It has already be done, \nand redoing just pretends that the girl calling sequencer tried to pretend \nthat she did it.\n\nIf the merge has been done already, it should not be redone.\n\nOnly if the user _explicitely_ specified a merge strategy, there _might_ \nbe a reason to redo the merge, but I still doubt it.\n\n> > >  (2) When $what is revert, this codepath shouldn't be exercised, \n> > >  should it?\n> > \n> > Yes.\n> \n> I haven't done a check intentionally, but there was a stupid thinko.\n> So you're right.\n> \n> But: this will only be a bug if the commit that _comes next in the\n> original history_ is to be reverted.\n\nDoes not matter.  It's a bug.\n\nA bug is almost always in the details, a corner-case, but it almost always \nneeds fixing nevertheless.\n\n> Nonetheless, purely tested:\n\n\"Nevertheless\", maybe?  \"untested\", maybe?\n\n> Johannes Schindelin wrote:\n> > I'd not check in sequencer for the strategy.  Especially given that we \n> > want to support user-written strategies in the future.\n> \n> I don't know how this is planned to look like, but perhaps \n> --list-strategies may make sense here, too.\n\nNo.  You just do not check for strategies.  Period.  git-merge does that, \nand you can easily abort a rebase if you explicitely asked for an invalid \nstrategy.\n\nBTW your coalescing multiple replies into one mail was a major pain in the \ndonkey.  Should you do that again, I will not even bother reading that \nmail.\n\nCiao,\nDscho\n"},{"id":"82185","messageId":"20080704003857.GG6677@leksak.fem-net","threadId":"14239","inReplyTo":"alpine.DEB.1.00.0807040138090.2849@eeepc-johanness","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-04T00:38:57Z","receivedAt":"2008-07-04T00:38:57Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn Fri, Jul 04, 2008 at 01:53:21AM +0200, Johannes Schindelin wrote:\n> On Thu, 3 Jul 2008, Stephan Beyer wrote:\n> > Btw, another root commit problem is btw that it's not possible to \n> > cherry-pick root commits.\n> \n> That is a problem to be fixed in cherry-pick, not in sequencer.  Care to \n> take care of that?\n\nNot at the moment but that's one of the things I note down for later ;-)\n\nAnd btw, somehow it is still open for me if builtin sequencer should be\na git-cherry-pick user (for pick) or if git-cherry-pick should be a\nsequencer user (which would result in a change of usage on cherry-pick\nconflicts).\n\n> > Johannes Schindelin wrote:\n> > > > > +# Usage: pick_one (cherry-pick|revert) [-*|--edit] sha1\n> > > > > +pick_one () {\n> > > > > +\twhat=\"$1\"\n> > > > > +\t# we just assume that this is either cherry-pick or revert\n> > > > > +\tshift\n> > > > > +\n> > > > > +\t# check for fast-forward if no options are given\n> > > > > +\tif expr \"x$1\" : 'x[^-]' >/dev/null\n> > > > > +\tthen\n> > > > > +\t\ttest \"$(git rev-parse --verify \"$1^\")\" = \\\n> > > > > +\t\t\t\"$(git rev-parse --verify HEAD)\" &&\n> > > > > +\t\t\toutput git reset --hard \"$1\" &&\n> > > > > +\t\t\treturn\n> > > > > +\tfi\n> > > > > +\ttest \"$1\" != '--edit' -a \"$what\" = 'revert' &&\n> > > > > +\t\twhat='revert --no-edit'\n> > > > \n> > > > This looks somewhat wrong.\n> > > > \n> > > > When the history looks like ---A---B and we are at A, cherry-picking B can\n> > > > be optimized to just advancing to B, but that optimization has a slight\n> > > > difference (or two) in the semantics.\n> > > > \n> > > >  (1) The committer information would not record the user and time of the\n> > > >      sequencer operation, which actually may be a good thing.\n> > > \n> > > This is debatable.  But I think you are correct, for all the same reasons \n> > > why a merge can result in a fast-forward.\n> > \n> > Dscho, you mean me by referring to 'you' here, right?\n> \n> Nope.\n> \n> > Otherwise I'm a bit confused: \"For the same reasons why a merge can \n> > result in a fast-forward we should not do fast forward here\" ;-)\n> \n> What I meant: there is no use here to redo it.  It has already be done, \n> and redoing just pretends that the girl calling sequencer tried to pretend \n> that she did it.\n> \n> If the merge has been done already, it should not be redone.\n> \n> Only if the user _explicitely_ specified a merge strategy, there _might_ \n> be a reason to redo the merge, but I still doubt it.\n\nI don't get the light bulb.  You're talking about \"the merge\", I am\ntalking about fast-forward on picks.\nPerhaps I got Junio wrong, too.\n\nI try a simple example just to go sure that we're talking about the\nsame.\n\nWe have commits\n\n  A ---- B ---- C ---- D\n       HEAD\n\nA is parent of B, B of C, C of D.\n\nNow we do:\n\tpick C\n\tpick --signoff D\n(Assume that the Signed-off-by: line is missing on D)\n\nWithout fast-forward, we get\n\n  A ---- B ---- C ---- D\n          \\\n           `--- C'---- D'\n                     HEAD\n\nC' differs in C only in the committer data, perhaps only committer date.\n\nWith fast-forward, we get:\n\n  A ---- B ---- C ---- D\n                 \\\n                  `--- D'\n                     HEAD\n\nIf Junio meant with\n>  (1) The committer information would not record the user and time of the\n>      sequencer operation, which actually may be a good thing.\nthat he thinks the first variant is the way to go, I strongly disagree.\nBut perhaps I'm getting everyone wrong these days ;)\n\n\n> > > >  (2) When $what is revert, this codepath shouldn't be exercised, \n> > > >  should it?\n> > > \n> > > Yes.\n> > \n> > I haven't done a check intentionally, but there was a stupid thinko.\n> > So you're right.\n> > \n> > But: this will only be a bug if the commit that _comes next in the\n> > original history_ is to be reverted.\n> \n> Does not matter.  It's a bug.\n> \n> A bug is almost always in the details, a corner-case, but it almost always \n> needs fixing nevertheless.\n\nOf course ;)\n\n> > Nonetheless, purely tested:\n> \n> \"Nevertheless\", maybe?  \"untested\", maybe?\n\nNo, I tested it once. ;-)\n(For the new single-quoted variant I've changed the author name in\nt3350).\n\n> > Johannes Schindelin wrote:\n> > > I'd not check in sequencer for the strategy.  Especially given that we \n> > > want to support user-written strategies in the future.\n> > \n> > I don't know how this is planned to look like, but perhaps \n> > --list-strategies may make sense here, too.\n> \n> No.  You just do not check for strategies.  Period.  git-merge does that, \n> and you can easily abort a rebase if you explicitely asked for an invalid \n> strategy.\n\nHmm, my dream of the \"robust sequencing after sanity check passed\" is\ndead with your \"period\".\nSo I'll have to check what happens, when e.g. \"--strategy=hours\" is used.\n(I mean, you should be in a safe state to do git sequencer --edit and\ncorrect \"hours\" to \"ours'.)\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82189","messageId":"alpine.DEB.1.00.0807040252490.2849@eeepc-johanness","threadId":"14239","inReplyTo":"20080704003857.GG6677@leksak.fem-net","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-07-04T01:03:37Z","receivedAt":"2008-07-04T01:03:37Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 4 Jul 2008, Stephan Beyer wrote:\n\n> On Fri, Jul 04, 2008 at 01:53:21AM +0200, Johannes Schindelin wrote:\n> > On Thu, 3 Jul 2008, Stephan Beyer wrote:\n> > > Btw, another root commit problem is btw that it's not possible to \n> > > cherry-pick root commits.\n> > \n> > That is a problem to be fixed in cherry-pick, not in sequencer.  Care \n> > to take care of that?\n> \n> Not at the moment but that's one of the things I note down for later ;-)\n\nWell, logically, it should come _before_ you use it in sequencer.  And you \nshould use it in sequencer.\n\n> And btw, somehow it is still open for me if builtin sequencer should be \n> a git-cherry-pick user (for pick) or if git-cherry-pick should be a \n> sequencer user (which would result in a change of usage on cherry-pick \n> conflicts).\n\nThe thing is, sequencer and cherry-pick _both_ use the same underlying \nfunctionality: cherry-picking a single commit.\n\nSo, logically, that part should be moved into libgit.a, and cherry-pick \nshould use the to-be-introduced sequencer() function.\n\n> > > Johannes Schindelin wrote:\n> > > > > > +# Usage: pick_one (cherry-pick|revert) [-*|--edit] sha1\n> > > > > > +pick_one () {\n> > > > > > +\twhat=\"$1\"\n> > > > > > +\t# we just assume that this is either cherry-pick or revert\n> > > > > > +\tshift\n> > > > > > +\n> > > > > > +\t# check for fast-forward if no options are given\n> > > > > > +\tif expr \"x$1\" : 'x[^-]' >/dev/null\n> > > > > > +\tthen\n> > > > > > +\t\ttest \"$(git rev-parse --verify \"$1^\")\" = \\\n> > > > > > +\t\t\t\"$(git rev-parse --verify HEAD)\" &&\n> > > > > > +\t\t\toutput git reset --hard \"$1\" &&\n> > > > > > +\t\t\treturn\n> > > > > > +\tfi\n> > > > > > +\ttest \"$1\" != '--edit' -a \"$what\" = 'revert' &&\n> > > > > > +\t\twhat='revert --no-edit'\n> > > > > \n> > > > > This looks somewhat wrong.\n> > > > > \n> > > > > When the history looks like ---A---B and we are at A, \n> > > > > cherry-picking B can be optimized to just advancing to B, but \n> > > > > that optimization has a slight difference (or two) in the \n> > > > > semantics.\n> > > > > \n> > > > >  (1) The committer information would not record the user and \n> > > > >      time of the sequencer operation, which actually may be a \n> > > > >      good thing.\n> > > > \n> > > > This is debatable.  But I think you are correct, for all the same \n> > > > reasons why a merge can result in a fast-forward.\n> > > \n> > > Dscho, you mean me by referring to 'you' here, right?\n> > \n> > Nope.\n> > \n> > > Otherwise I'm a bit confused: \"For the same reasons why a merge can \n> > > result in a fast-forward we should not do fast forward here\" ;-)\n> > \n> > What I meant: there is no use here to redo it.  It has already be \n> > done, and redoing just pretends that the girl calling sequencer tried \n> > to pretend that she did it.\n> > \n> > If the merge has been done already, it should not be redone.\n> > \n> > Only if the user _explicitely_ specified a merge strategy, there _might_ \n> > be a reason to redo the merge, but I still doubt it.\n> \n> I don't get the light bulb.  You're talking about \"the merge\", I am\n> talking about fast-forward on picks.\n\nOoops.  I think I was talking about a later comment of Junio's.\n\nThe thing is, if you try to pick a commit, and the current revision is \nalready the parent of that commit, I think it would be wrong to redo the \ncommit, pretending that the current time and committer were applying that \ncommit.\n\n> I try a simple example just to go sure that we're talking about the \n> same.\n> \n> We have commits\n> \n>   A ---- B ---- C ---- D\n>        HEAD\n> \n> A is parent of B, B of C, C of D.\n> \n> Now we do:\n> \tpick C\n> \tpick --signoff D\n> (Assume that the Signed-off-by: line is missing on D)\n> \n> Without fast-forward, we get\n> \n>   A ---- B ---- C ---- D\n>           \\\n>            `--- C'---- D'\n>                      HEAD\n> \n> C' differs in C only in the committer data, perhaps only committer date.\n> \n> With fast-forward, we get:\n> \n>   A ---- B ---- C ---- D\n>                  \\\n>                   `--- D'\n>                      HEAD\n\nIMO the --signoff should check if the sign off is present (must be the \nlast one, as if we redid that commit), and if it is, fast-forward.\n\nIf it is missing, we need to redo the commit.\n\n> > > Johannes Schindelin wrote:\n> > > > I'd not check in sequencer for the strategy.  Especially given \n> > > > that we want to support user-written strategies in the future.\n> > > \n> > > I don't know how this is planned to look like, but perhaps \n> > > --list-strategies may make sense here, too.\n> > \n> > No.  You just do not check for strategies.  Period.  git-merge does \n> > that, and you can easily abort a rebase if you explicitely asked for \n> > an invalid strategy.\n> \n> Hmm, my dream of the \"robust sequencing after sanity check passed\" is\n> dead with your \"period\".\n>\n> So I'll have to check what happens, when e.g. \"--strategy=hours\" is \n> used.\n\nWow.  Is that the CVS/SVN merge strategy?\n\nDo not care too much about the rare use cases.  Only experts will use -s.\n\nBut experts are known to shoot themselves, or inflict other pain on their \nbodies, so it is okay to let them suffer from a typo.\n\nCiao,\nDscho\n"},{"id":"82190","messageId":"20080704010616.GH6677@leksak.fem-net","threadId":"14239","inReplyTo":"alpine.DEB.1.00.0807040138090.2849@eeepc-johanness","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-04T01:06:16Z","receivedAt":"2008-07-04T01:06:16Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi again,\n\nJohannes Schindelin wrote:\n> > > I'd not check in sequencer for the strategy.  Especially given that we \n> > > want to support user-written strategies in the future.\n> > \n> > I don't know how this is planned to look like, but perhaps \n> > --list-strategies may make sense here, too.\n\nFunny, a merge with an unknown merge strategy acts somehow like my\nproposed --list-strategies (at least on git-merge.sh, haven't checked\non builtin-merge)\nBut that is just a silly side note.\n\n> No.  You just do not check for strategies.  Period.\n\nWell, I've seen that my strategy_check (which is now removed) only\nproduces a warning, so it had no big effect at all.\nSo I've tested merge --strategy=hours (to simulate a typo):\n\n-- -- snip paste -- --\nTesting:\n        git sequencer todotest1\n\navailable strategies are: recur recursive octopus resolve stupid ours subtree\nError merging\n* FAIL 33: merge multiple branches and --reuse-commit works\n-- -- snap paste -- --\n\nThat means, with the information that can be seen, a user should easily be\nable to fix that, i.e. run git-sequencer --edit and fix the line.\n\nSo I accept your period sign now ;-)\n\n> and you can easily abort a rebase if you explicitely asked for an invalid \n> strategy.\n\nAborting after fixing a lot of conflicts in the sequencer process is\nreally annoying.  So I've chosen to never abort automatically.\n(That was one of the first things that I changed after I first used my\nown sequencer for real work and not only test cases.)\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82192","messageId":"alpine.DEB.1.00.0807040309580.2849@eeepc-johanness","threadId":"14239","inReplyTo":"20080704010616.GH6677@leksak.fem-net","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-07-04T01:11:51Z","receivedAt":"2008-07-04T01:11:51Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 4 Jul 2008, Stephan Beyer wrote:\n\n> Johannes Schindelin wrote:\n>\n> > and you can easily abort a rebase if you explicitely asked for an \n> > invalid strategy.\n> \n> Aborting after fixing a lot of conflicts in the sequencer process is \n> really annoying.\n\nI think it should use rerere (if activated, which I have given up \nadvocating to be the default).\n\n> So I've chosen to never abort automatically.\n\nWho said anything about automatically?  Of _course_, the user has to abort \nit.  Or try to continue with \"git sequencer --continue -s ours\".\n\nCiao,\nDscho\n"},{"id":"82194","messageId":"20080704015326.GI6677@leksak.fem-net","threadId":"14239","inReplyTo":"alpine.DEB.1.00.0807040252490.2849@eeepc-johanness","subject":"Re: [RFC/PATCH 1/4] Add git-sequencer shell prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-04T01:53:26Z","receivedAt":"2008-07-04T01:53:26Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn Fri, Jul 04, 2008 at 03:03:37AM +0200, Johannes Schindelin wrote:\n> On Fri, 4 Jul 2008, Stephan Beyer wrote:\n> > On Fri, Jul 04, 2008 at 01:53:21AM +0200, Johannes Schindelin wrote:\n> > > On Thu, 3 Jul 2008, Stephan Beyer wrote:\n> > > > Btw, another root commit problem is btw that it's not possible to \n> > > > cherry-pick root commits.\n> > > \n> > > That is a problem to be fixed in cherry-pick, not in sequencer.  Care \n> > > to take care of that?\n> > \n> > Not at the moment but that's one of the things I note down for later ;-)\n> \n> Well, logically, it should come _before_ you use it in sequencer.  And you \n> should use it in sequencer.\n\nYet nobody seems to have asked for a cherry-pick that is able to pick\nroot commits and sequencer is not closed source after GSoC, so this can\nbe added whenever there is need and time for it.\nThat's what I wanted to say with \"note down for later\". ;-)\n\n> > I don't get the light bulb.  You're talking about \"the merge\", I am\n> > talking about fast-forward on picks.\n> \n> Ooops.  I think I was talking about a later comment of Junio's.\n> \n> The thing is, if you try to pick a commit, and the current revision is \n> already the parent of that commit, I think it would be wrong to redo the \n> commit, pretending that the current time and committer were applying that \n> commit.\n\nRight.\n\n> IMO the --signoff should check if the sign off is present (must be the \n> last one, as if we redid that commit), and if it is, fast-forward.\n> \n> If it is missing, we need to redo the commit.\n\nThat's a good point.\nChecked that and it's even a bug in the sequencer: on fast-forwards, no\nsignoff is added.\n\nThis should fix that:\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -219,8 +219,6 @@ pick_one () {\n \t\tfi\n \t\t;;\n \tesac\n-\ttest -n \"$SIGNOFF\" &&\n-\t\twhat=\"$what -s\"\n \t$use_perform git $what \"$@\"\n }\n \n@@ -973,16 +971,21 @@ insn_pick () {\n \t\t$use_perform git commit --amend $EDIT $signoff --no-verify \\\n \t\t\t--author \"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\" \\\n \t\t\t--message=\"$MESSAGE\"\n-\telse\n+\telif test -n \"$AUTHOR\"\n+\tthen\n \t\t# correct author if AUTHOR is set\n-\t\ttest -n \"$AUTHOR\" &&\n-\t\t\t$use_perform git commit --amend $EDIT --no-verify -C HEAD \\\n-\t\t\t\t--author \"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\"\n-\t\t# XXX: a git-cherry-pick --author could be nicer here\n+\t\t$use_perform git commit --amend $EDIT --no-verify -C HEAD \\\n+\t\t\t--author \"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\"\n+\telif test -n \"$MESSAGE\"\n+\tthen\n \t\t# correct commit message if MESSAGE is set\n-\t\ttest -n \"$MESSAGE\" &&\n-\t\t\t$use_perform git commit --amend $EDIT $signoff --no-verify \\\n-\t\t\t\t-C HEAD --message=\"$MESSAGE\"\n+\t\t$use_perform git commit --amend $EDIT $signoff --no-verify \\\n+\t\t\t-C HEAD --message=\"$MESSAGE\"\n+\telif test -n \"$SIGNOFF\"\n+\tthen\n+\t\t# only add signoff\n+\t\t$use_perform git commit --amend $EDIT $signoff --no-verify \\\n+\t\t\t-C HEAD\n \tfi\n \n \treturn 0\n###\n\nAh, and that is poorly tested, but not untested. :) See:\n\t$ git checkout -b seq-proto-dev3 HEAD^\n\tSwitched to a new branch \"seq-proto-dev3\"\n\t$ git sequencer\n\tmark :1\n\tpick seq-proto-dev2\n\tref refs/test/no\n\treset :1\n\tpick --signoff seq-proto-dev2\nNow: seq-proto-dev3 has signoff and seq-proto-dev2 and refs/test/no have the\nsame SHA1.  And the test suite passes.\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82234","messageId":"alpine.DEB.1.00.0807041617320.9925@racer","threadId":"14239","inReplyTo":"20080704015326.GI6677@leksak.fem-net","subject":"[PATCH] Allow cherry-picking root commits","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-07-04T15:19:52Z","receivedAt":"2008-07-04T15:19:52Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThere is no good reason why cherry-picking root commits should not be \nallowed.\n\nFurther, since cherry-pick is the working horse of git-rebase, we _should_ \nallow picking root commits, so that you can rebase originally independent \nbranches on top of another branch.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tOn Fri, 4 Jul 2008, Stephan Beyer wrote:\n\n\t> On Fri, Jul 04, 2008 at 03:03:37AM +0200, Johannes Schindelin \n\t> wrote:\n\t> \n\t> > Well, logically, it should come _before_ you use it in \n\t> > sequencer.  And you should use it in sequencer.\n\t> \n\t> Yet nobody seems to have asked for a cherry-pick that is able to \n\t> pick root commits and sequencer is not closed source after GSoC, so \n\t> this can be added whenever there is need and time for it.\n\n\tHowever, this is the wrong sequence.\n\n\tAnyhow, I give up on trying to convince you.\n\n builtin-revert.c            |   26 ++++++++++++++++----------\n t/t3503-cherry-pick-root.sh |   30 ++++++++++++++++++++++++++++++\n 2 files changed, 46 insertions(+), 10 deletions(-)\n create mode 100755 t/t3503-cherry-pick-root.sh\n\ndiff --git a/builtin-revert.c b/builtin-revert.c\nindex 0270f9b..f3d4524 100644\n--- a/builtin-revert.c\n+++ b/builtin-revert.c\n@@ -206,6 +206,7 @@ static int merge_recursive(const char *base_sha1,\n {\n \tchar buffer[256];\n \tconst char *argv[6];\n+\tint i = 0;\n \n \tsprintf(buffer, \"GITHEAD_%s\", head_sha1);\n \tsetenv(buffer, head_name, 1);\n@@ -218,12 +219,13 @@ static int merge_recursive(const char *base_sha1,\n \t * and $prev on top of us (when reverting), or the change between\n \t * $prev and $commit on top of us (when cherry-picking or replaying).\n \t */\n-\targv[0] = \"merge-recursive\";\n-\targv[1] = base_sha1;\n-\targv[2] = \"--\";\n-\targv[3] = head_sha1;\n-\targv[4] = next_sha1;\n-\targv[5] = NULL;\n+\targv[i++] = \"merge-recursive\";\n+\tif (base_sha1)\n+\t\targv[i++] = base_sha1;\n+\targv[i++] = \"--\";\n+\targv[i++] = head_sha1;\n+\targv[i++] = next_sha1;\n+\targv[i++] = NULL;\n \n \treturn run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD);\n }\n@@ -297,9 +299,12 @@ static int revert_or_cherry_pick(int argc, const char **argv)\n \t\tdiscard_cache();\n \t}\n \n-\tif (!commit->parents)\n-\t\tdie (\"Cannot %s a root commit\", me);\n-\tif (commit->parents->next) {\n+\tif (!commit->parents) {\n+\t\tif (action == REVERT)\n+\t\t\tdie (\"Cannot revert a root commit\");\n+\t\tparent = NULL;\n+\t}\n+\telse if (commit->parents->next) {\n \t\t/* Reverting or cherry-picking a merge commit */\n \t\tint cnt;\n \t\tstruct commit_list *p;\n@@ -368,7 +373,8 @@ static int revert_or_cherry_pick(int argc, const char **argv)\n \t\t}\n \t}\n \n-\tif (merge_recursive(sha1_to_hex(base->object.sha1),\n+\tif (merge_recursive(base == NULL ?\n+\t\t\t\tNULL : sha1_to_hex(base->object.sha1),\n \t\t\t\tsha1_to_hex(head), \"HEAD\",\n \t\t\t\tsha1_to_hex(next->object.sha1), oneline) ||\n \t\t\twrite_cache_as_tree(head, 0, NULL)) {\ndiff --git a/t/t3503-cherry-pick-root.sh b/t/t3503-cherry-pick-root.sh\nnew file mode 100755\nindex 0000000..b0faa29\n--- /dev/null\n+++ b/t/t3503-cherry-pick-root.sh\n@@ -0,0 +1,30 @@\n+#!/bin/sh\n+\n+test_description='test cherry-picking a root commit'\n+\n+. ./test-lib.sh\n+\n+test_expect_success setup '\n+\n+\techo first > file1 &&\n+\tgit add file1 &&\n+\ttest_tick &&\n+\tgit commit -m \"first\" &&\n+\n+\tgit symbolic-ref HEAD refs/heads/second &&\n+\trm .git/index file1 &&\n+\techo second > file2 &&\n+\tgit add file2 &&\n+\ttest_tick &&\n+\tgit commit -m \"second\"\n+\n+'\n+\n+test_expect_success 'cherry-pick a root commit' '\n+\n+\tgit cherry-pick master &&\n+\ttest first = $(cat file1)\n+\n+'\n+\n+test_done\n-- \n1.5.6.1.376.g6b0fd\n"},{"id":"82239","messageId":"20080704164141.GA28515@leksak.fem-net","threadId":"14239","inReplyTo":"alpine.DEB.1.00.0807041617320.9925@racer","subject":"Re: [PATCH] Allow cherry-picking root commits","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-04T16:41:41Z","receivedAt":"2008-07-04T16:41:41Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"On Fri, Jul 04, 2008 at 04:19:52PM +0100, Johannes Schindelin wrote:\n> \tAnyhow, I give up on trying to convince you.\n\nGreat :)\nBig thanks for the patch!\n\nIt also works with my rebase-i variant with just an unimportant \"fatal\"\nwhich can be shut up by\n--- a/git-sequencer.sh\n+++ b/git-sequencer.sh\n@@ -211,7 +211,7 @@ pick_one () {\n \t\t;;\n \tcherry-pick,*)\n \t\t# fast forward\n-\t\tif test \"$(git rev-parse --verify \"$1^\")\" = \\\n+\t\tif test \"$(git rev-parse --verify \"$1^\" 2>/dev/null)\" = \\\n \t\t\t\"$(git rev-parse --verify HEAD)\"\n \t\tthen\n \t\t\tperform git reset --hard \"$1\"\n###\n\nRegards.\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82257","messageId":"20080704210052.GA6984@steel.home","threadId":"14239","inReplyTo":"1214879914-17866-1-git-send-email-s-beyer@gmx.net","subject":"Re: git sequencer prototype","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2008-07-04T21:00:52Z","receivedAt":"2008-07-04T21:00:52Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"Stephan Beyer, Tue, Jul 01, 2008 04:38:30 +0200:\n> Hi,\n> \n> here is the patchset for the git-sequencer prototype, documentation,\n> test suite and a first git-am and git-rebase-i migration.\n> Indeed, monster patches. ;)\n\nBTW, how about renaming it in something short: git seq. There is\nalready a seq(1) in GNU coreutils, which does roughly the same (prints\na sequence of numbers), why not reuse the name?\n"},{"id":"82259","messageId":"7vwsk1ti6y.fsf@gitster.siamese.dyndns.org","threadId":"14239","inReplyTo":"20080704210052.GA6984@steel.home","subject":"Re: git sequencer prototype","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-04T22:09:41Z","receivedAt":"2008-07-04T22:09:41Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alex Riesen <raa.lkml@gmail.com> writes:\n\n> Stephan Beyer, Tue, Jul 01, 2008 04:38:30 +0200:\n>> Hi,\n>> \n>> here is the patchset for the git-sequencer prototype, documentation,\n>> test suite and a first git-am and git-rebase-i migration.\n>> Indeed, monster patches. ;)\n>\n> BTW, how about renaming it in something short: git seq. There is\n> already a seq(1) in GNU coreutils, which does roughly the same (prints\n> a sequence of numbers), why not reuse the name?\n\nIs it advantageous to use shorter but less descriptive name for this\ncommand?  It will be a backend to am/rebase and not something the users\nwill type from the command line, won't it?\n"},{"id":"82260","messageId":"20080704222353.GC28515@leksak.fem-net","threadId":"14239","inReplyTo":"7vwsk1ti6y.fsf@gitster.siamese.dyndns.org","subject":"Re: git sequencer prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-04T22:23:53Z","receivedAt":"2008-07-04T22:23:53Z","isPatch":false,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Junio C Hamano <gitster@pobox.com> wrote:\n> Alex Riesen <raa.lkml@gmail.com> writes:\n> > BTW, how about renaming it in something short: git seq. There is\n> > already a seq(1) in GNU coreutils, which does roughly the same (prints\n> > a sequence of numbers), why not reuse the name?\n> \n> Is it advantageous to use shorter but less descriptive name for this\n> command?\n\nI also think descriptive names are nice for git even if the user should\ntype that, since tab completion exists.\nWhen I've started with git, I loved the fact that I could use tab\ncompletion to learn new git commands and that often the name was\ndescriptive enough to get an imagination of what the tool could do (and\nthen read the manpage to verify...)\n\n> It will be a backend to am/rebase and not something the users\n> will type from the command line, won't it?\n\nUsually, but for special cases it is also nicely usable by the user\nand the --status and --edit subcommands are intended to be used by the\nuser, too.\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82275","messageId":"20080705081321.GA4935@blimp.local","threadId":"14239","inReplyTo":"7vwsk1ti6y.fsf@gitster.siamese.dyndns.org","subject":"Re: git sequencer prototype","fromName":"Alex Riesen","fromEmail":"fork0@users.sourceforge.net","sentAt":"2008-07-05T08:13:21Z","receivedAt":"2008-07-05T08:13:21Z","isPatch":false,"sender":{"key":"fork0@users.sourceforge.net","avatar":null},"body":"Junio C Hamano, Sat, Jul 05, 2008 00:09:41 +0200:\n> Alex Riesen <raa.lkml@gmail.com> writes:\n> \n> > Stephan Beyer, Tue, Jul 01, 2008 04:38:30 +0200:\n> >> Hi,\n> >> \n> >> here is the patchset for the git-sequencer prototype, documentation,\n> >> test suite and a first git-am and git-rebase-i migration.\n> >> Indeed, monster patches. ;)\n> >\n> > BTW, how about renaming it in something short: git seq. There is\n> > already a seq(1) in GNU coreutils, which does roughly the same (prints\n> > a sequence of numbers), why not reuse the name?\n> \n> Is it advantageous to use shorter but less descriptive name for this\n> command?  It will be a backend to am/rebase and not something the users\n> will type from the command line, won't it?\n\nThere is not a huge lot of possible meanings of \"seq\" in the given\ncontext. Somehow I find it hard to believe someone will be confused by\na backend command with a short name \"seq\" (seq-uence-something?)\n\nIt'll make the lines shorter, less need to wrap them.\n\nBTW, what does \"am\" (git am) mean?\n"},{"id":"82278","messageId":"18071eea0807050312m2f5a60ebyb86177f6b10f3a7e@mail.gmail.com","threadId":"14239","inReplyTo":"20080705081321.GA4935@blimp.local","subject":"Re: git sequencer prototype","fromName":"Thomas Adam","fromEmail":"thomas.adam22@gmail.com","sentAt":"2008-07-05T10:12:36Z","receivedAt":"2008-07-05T10:12:36Z","isPatch":false,"sender":{"key":"thomas.adam22@gmail.com","avatar":"https://gravatar.com/avatar/137f9858bc6bfd5b2f743aefd988c81ce0cbd306248889df80e269519cfc8741?d=mp&s=160"},"body":"2008/7/5 Alex Riesen <fork0@users.sourceforge.net>:\n> BTW, what does \"am\" (git am) mean?\n\nI always thought of it as \"apply mbox\".\n\n-- Thomas Adam\n"},{"id":"82279","messageId":"alpine.DEB.1.00.0807051210530.3334@eeepc-johanness","threadId":"14239","inReplyTo":"20080705081321.GA4935@blimp.local","subject":"Re: git sequencer prototype","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-07-05T10:13:31Z","receivedAt":"2008-07-05T10:13:31Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 5 Jul 2008, Alex Riesen wrote:\n\n> Junio C Hamano, Sat, Jul 05, 2008 00:09:41 +0200:\n> > Alex Riesen <raa.lkml@gmail.com> writes:\n> > \n> > > Stephan Beyer, Tue, Jul 01, 2008 04:38:30 +0200:\n> > >> \n> > >> here is the patchset for the git-sequencer prototype, \n> > >> documentation, test suite and a first git-am and git-rebase-i \n> > >> migration. Indeed, monster patches. ;)\n> > >\n> > > BTW, how about renaming it in something short: git seq. There is \n> > > already a seq(1) in GNU coreutils, which does roughly the same \n> > > (prints a sequence of numbers), why not reuse the name?\n> > \n> > Is it advantageous to use shorter but less descriptive name for this \n> > command?  It will be a backend to am/rebase and not something the \n> > users will type from the command line, won't it?\n> \n> There is not a huge lot of possible meanings of \"seq\" in the given \n> context. Somehow I find it hard to believe someone will be confused by a \n> backend command with a short name \"seq\" (seq-uence-something?)\n\nIt might be a bit confusing, since \"seq\" _produces_ sequences, and \n\"sequencer\" is kind of an assembly line, getting commits in a sequence and \nthen applying the corresponding changes in order.\n\n> It'll make the lines shorter, less need to wrap them.\n\nBy that reasoning, we should have git-a, git-b, ... but that would not \nimprove readability.\n\n> BTW, what does \"am\" (git am) mean?\n\nIt means \"applymbox\", but that name was already taken.  And \"am\" turned \nout _not_ to replace \"applymbox\" right away as was expected, so it is a \nbit of unfortunate history.\n\nCiao,\nDscho\n"},{"id":"82289","messageId":"1215277137-20879-1-git-send-email-s-beyer@gmx.net","threadId":"14239","inReplyTo":"1214879914-17866-2-git-send-email-s-beyer@gmx.net","subject":"[PATCH v2 1/4] Add git-sequencer shell prototype","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-05T16:58:57Z","receivedAt":"2008-07-05T16:58:57Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"git sequencer is planned as a backend for user scripts\nthat execute a sequence of git instructions and perhaps\nneed manual intervention, for example git-rebase or git-am.\n\nMentored-by: Christian Couder <chriscool@tuxfamily.org>\nMentored-by: Daniel Barkalow <barkalow@iabervon.org>\nSigned-off-by: Stephan Beyer <s-beyer@gmx.net>\n---\nHi,\n\nthis should now contain your suggestions (where I posted interdiffs)\nand some further bugfixes of bugs I stumbled across.\n(If you prefer an interdiff to v1, I can also send one...)\n\nRegards,\n  Stephan\n\n .gitignore       |    1 +\n Makefile         |    1 +\n command-list.txt |    1 +\n git-sequencer.sh | 1921 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 4 files changed, 1924 insertions(+), 0 deletions(-)\n create mode 100755 git-sequencer.sh\n\ndiff --git a/.gitignore b/.gitignore\nindex 4ff2fec..65a075b 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -111,6 +111,7 @@ git-revert\n git-rm\n git-send-email\n git-send-pack\n+git-sequencer\n git-sh-setup\n git-shell\n git-shortlog\ndiff --git a/Makefile b/Makefile\nindex 78e08d3..9db1a43 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -250,6 +250,7 @@ SCRIPT_SH += git-rebase--interactive.sh\n SCRIPT_SH += git-rebase.sh\n SCRIPT_SH += git-repack.sh\n SCRIPT_SH += git-request-pull.sh\n+SCRIPT_SH += git-sequencer.sh\n SCRIPT_SH += git-sh-setup.sh\n SCRIPT_SH += git-stash.sh\n SCRIPT_SH += git-submodule.sh\ndiff --git a/command-list.txt b/command-list.txt\nindex 3583a33..44bb5b0 100644\n--- a/command-list.txt\n+++ b/command-list.txt\n@@ -101,6 +101,7 @@ git-rev-parse                           ancillaryinterrogators\n git-rm                                  mainporcelain common\n git-send-email                          foreignscminterface\n git-send-pack                           synchingrepositories\n+git-sequencer                           plumbingmanipulators\n git-shell                               synchelpers\n git-shortlog                            mainporcelain\n git-show                                mainporcelain common\ndiff --git a/git-sequencer.sh b/git-sequencer.sh\nnew file mode 100755\nindex 0000000..e4e4aad\n--- /dev/null\n+++ b/git-sequencer.sh\n@@ -0,0 +1,1921 @@\n+#!/bin/sh\n+# A git sequencer prototype.\n+\n+SUBDIRECTORY_OK=Yes\n+OPTIONS_KEEPDASHDASH=\n+OPTIONS_SPEC=\"\\\n+git-sequencer [options] [--] [<file>]\n+git-sequencer (--continue | --abort | --skip | --edit | --status)\n+--\n+ Options to start a sequencing process\n+B,batch        run in batch-mode\n+onto=          checkout the given commit or branch first\n+q,quiet        suppress output\n+v,verbose      be more verbose\n+ Options to restart/change a sequencing process or show information\n+continue       continue paused sequencer process\n+abort          restore original branch and abort\n+skip           skip current patch and continue\n+status         show the status of the sequencing process\n+edit           invoke editor to let user edit the remaining insns\n+ Options to be used by user scripts\n+caller=        provide information string: name|abort|cont|skip\n+\"\n+\n+. git-sh-setup\n+require_work_tree\n+\n+git var GIT_COMMITTER_IDENT >/dev/null ||\n+\tdie 'You need to set your committer info first'\n+\n+SEQ_DIR=\"$GIT_DIR/sequencer\"\n+TODO=\"$SEQ_DIR/todo\"\n+DONE=\"$SEQ_DIR/done\"\n+MSG=\"$SEQ_DIR/message\"\n+PATCH=\"$SEQ_DIR/patch\"\n+AUTHOR_SCRIPT=\"$SEQ_DIR/author-script\"\n+ORIG_AUTHOR_SCRIPT=\"$SEQ_DIR/author-script.orig\"\n+CALLER_SCRIPT=\"$SEQ_DIR/caller-script\"\n+WHY_FILE=\"$SEQ_DIR/why\"\n+MARK_PREFIX='refs/sequencer-marks'\n+\n+warn () {\n+\techo \"$*\" >&2\n+}\n+\n+cleanup () {\n+\tfor ref in $(git for-each-ref --format='%(refname)' \"$MARK_PREFIX\")\n+\tdo\n+\t\tgit update-ref -d \"$ref\" \"$ref\" || return\n+\tdone\n+\trm -rf \"$SEQ_DIR\"\n+}\n+\n+# Die if there has been a conflict\n+die_to_continue () {\n+\twarn \"$*\"\n+\ttest -z \"$BATCHMODE\" ||\n+\t\tdie_abort 'Aborting, because of batch mode.'\n+\ttest -z \"$WHY\" &&\n+\t\techo 'conflict' >\"$WHY_FILE\" ||\n+\t\techo \"$WHY\" >\"$WHY_FILE\"\n+\texit 3\n+}\n+\n+die_abort () {\n+\trestore\n+\tcleanup\n+\tdie \"$1\"\n+}\n+\n+quit () {\n+\tcleanup\n+\ttest -z \"$*\" ||\n+\t\techo \"$*\"\n+\texit 0\n+}\n+\n+perform () {\n+\tcase \"$VERBOSE\" in\n+\t0)\n+\t\t\"$@\" >/dev/null\n+\t\t;;\n+\t1)\n+\t\toutput=$(\"$@\" 2>&1 )\n+\t\tstatus=$?\n+\t\ttest $status -ne 0 && printf '%s\\n' \"$output\"\n+\t\treturn $status\n+\t\t;;\n+\t2)\n+\t\t\"$@\"\n+\t\t;;\n+\tesac\n+}\n+\n+require_clean_work_tree () {\n+\t# test if working tree is dirty\n+\tgit rev-parse --verify HEAD >/dev/null &&\n+\tgit update-index --ignore-submodules --refresh &&\n+\tgit diff-files --quiet --ignore-submodules &&\n+\tgit diff-index --cached --quiet HEAD --ignore-submodules -- ||\n+\tdie 'Working tree is dirty'\n+}\n+\n+ORIG_REFLOG_ACTION=\"$GIT_REFLOG_ACTION\"\n+\n+comment_for_reflog () {\n+\tif test -z \"$ORIG_REFLOG_ACTION\"\n+\tthen\n+\t\tGIT_REFLOG_ACTION='sequencer'\n+\t\ttest -z \"$CALLER\" ||\n+\t\t\tGIT_REFLOG_ACTION=\"$GIT_REFLOG_ACTION ($CALLER)\"\n+\t\texport GIT_REFLOG_ACTION\n+\tfi\n+}\n+\n+# Get commit message from commit $1\n+commit_message () {\n+\tgit cat-file commit \"$1\" | sed -e '1,/^$/d'\n+}\n+\n+LAST_COUNT=\n+mark_action_done () {\n+\tsed -e 1q <\"$TODO\" >>\"$DONE\"\n+\tsed -e 1d <\"$TODO\" >\"$TODO.new\"\n+\tmv -f \"$TODO.new\" \"$TODO\"\n+\tif test \"$VERBOSE\" -gt 0\n+\tthen\n+\t\tcount=$(grep -c '^[^#]' <\"$DONE\")\n+\t\ttotal=$(expr \"$count\" + \"$(grep -c '^[^#]' <\"$TODO\")\")\n+\t\tif test \"$LAST_COUNT\" != \"$count\"\n+\t\tthen\n+\t\t\tLAST_COUNT=\"$count\"\n+\t\t\ttest \"$VERBOSE\" -lt 1 ||\n+\t\t\t\tprintf 'Sequencing (%d/%d)\\r' \"$count\" \"$total\"\n+\t\t\ttest \"$VERBOSE\" -lt 2 || echo\n+\t\tfi\n+\tfi\n+}\n+\n+# Generate message, patch and author script files\n+make_patch () {\n+\tparent_sha1=$(git rev-parse --verify \"$1^\" 2>/dev/null ||\n+\t\techo '--root')\n+\tgit diff-tree -p \"$parent_sha1\" \"$1\" >\"$PATCH\"\n+\ttest -f \"$MSG\" ||\n+\t\tcommit_message \"$1\" >\"$MSG\"\n+\ttest -f \"$AUTHOR_SCRIPT\" ||\n+\t\tget_author_ident_from_commit \"$1\" >\"$AUTHOR_SCRIPT\"\n+}\n+\n+# Generate a patch and die with \"conflict\" status code\n+die_with_patch () {\n+\tmake_patch \"$1\"\n+\tgit rerere\n+\tdie_to_continue \"$2\"\n+}\n+\n+restore () {\n+\tgit rerere clear\n+\n+\tread HEADNAME <\"$SEQ_DIR/head-name\"\n+\tread HEAD <\"$SEQ_DIR/head\"\n+\tcase $HEADNAME in\n+\trefs/*)\n+\t\tgit symbolic-ref HEAD \"$HEADNAME\"\n+\t\t;;\n+\tesac &&\n+\tperform git reset --hard \"$HEAD\"\n+}\n+\n+has_action () {\n+\tgrep '^[^#]' \"$1\" >/dev/null\n+}\n+\n+# Check if text file $1 contains a commit message\n+has_message () {\n+\ttest -n \"$(sed -n -e '/^Signed-off-by:/d;/^[^#]/p' <\"$1\")\"\n+}\n+\n+# Count parents of commit $1\n+count_parents() {\n+\tgit cat-file commit \"$1\" | sed -n -e '1,/^$/p' | grep -c '^parent'\n+}\n+\n+# Evaluate the author script to get author information to\n+# apply it with \"with_author git foo\" then.\n+get_current_author () {\n+\tif test -f \"$AUTHOR_SCRIPT\"\n+\tthen\n+\t\t. \"$AUTHOR_SCRIPT\"\n+\telse\n+\t\t. \"$ORIG_AUTHOR_SCRIPT\"\n+\tfi || die_abort 'Author script is damaged. This must not happen!'\n+}\n+\n+# Run command with author information\n+with_author () {\n+\tGIT_AUTHOR_NAME=\"$GIT_AUTHOR_NAME\" \\\n+\tGIT_AUTHOR_EMAIL=\"$GIT_AUTHOR_EMAIL\" \\\n+\tGIT_AUTHOR_DATE=\"$GIT_AUTHOR_DATE\" \\\n+\t\t\"$@\"\n+}\n+\n+# clean WHY_FILE and reset WHY\n+clean_why () {\n+\trm -f \"$WHY_FILE\"\n+\tWHY=\n+}\n+\n+# Usage: pick_one (cherry-pick|revert) [-*|--edit] sha1\n+pick_one () {\n+\twhat=\"$1\"\n+\tshift\n+\n+\tcase \"$what,$1\" in\n+\trevert,*)\n+\t\ttest \"$1\" != '--edit' &&\n+\t\t\twhat='revert --no-edit'\n+\t\t;;\n+\tcherry-pick,-*)\n+\t\t;;\n+\tcherry-pick,*)\n+\t\t# fast forward\n+\t\tif test \"$(git rev-parse --verify \"$1^\" 2>/dev/null)\" = \\\n+\t\t\t\"$(git rev-parse --verify HEAD)\"\n+\t\tthen\n+\t\t\tperform git reset --hard \"$1\"\n+\t\t\treturn\n+\t\tfi\n+\t\t;;\n+\tesac\n+\t$use_perform git $what \"$@\"\n+}\n+\n+nth_string () {\n+\tcase \"$1\" in\n+\t*1[0-9]|*[04-9])\n+\t\techo \"$1th\"\n+\t\t;;\n+\t*1)\n+\t\techo \"$1st\"\n+\t\t;;\n+\t*2)\n+\t\techo \"$1nd\"\n+\t\t;;\n+\t*3)\n+\t\techo \"$1rd\"\n+\t\t;;\n+\tesac\n+}\n+\n+make_squash_message () {\n+\tif test -f \"$squash_msg\"\n+\tthen\n+\t\tcount=$(($(sed -n -e 's/^# This is [^0-9]*\\([1-9][0-9]*\\).*/\\1/p' \\\n+\t\t\t<\"$squash_msg\" | sed -n -e '$p')+1))\n+\t\techo \"# This is a combination of $count commits.\"\n+\t\tsed -e '1d' -e '2,/^./{\n+\t\t\t/^$/d\n+\t\t}' <\"$squash_msg\"\n+\telse\n+\t\tcount=2\n+\t\techo '# This is a combination of 2 commits.'\n+\t\techo '# The first commit message is:'\n+\t\techo\n+\t\tcommit_message HEAD\n+\tfi\n+\techo\n+\techo \"# This is the $(nth_string \"$count\") commit message:\"\n+\techo\n+\tcommit_message \"$1\"\n+}\n+\n+make_squash_message_multiple () {\n+\trevlist=$(git rev-list --reverse \"$sha1..HEAD\")\n+\tcount=$(echo \"$revlist\" | wc -l)\n+\tsquash_i=0\n+\techo \"# This is a combination of $count commits.\"\n+\tfor cur_sha1 in $revlist\n+\tdo\n+\t\tsquash_i=$(($squash_i+1))\n+\t\tif test -f \"$squash_msg\"\n+\t\tthen\n+\t\t\tcount=$(($count + $(sed -n -e \\\n+\t\t\t\t's/^# This is [^0-9]*\\([1-9][0-9]*\\).*/\\1/p' \\\n+\t\t\t\t<\"$squash_msg\" | sed -n -e '$p')+1))\n+\t\t\tsed -e '1d' -e '2,/^./{\n+\t\t\t\t/^$/d\n+\t\t\t}' <\"$squash_msg\"\n+\t\tfi\n+\t\techo\n+\t\techo \"# This is the $(nth_string \"$squash_i\") commit message:\"\n+\t\techo\n+\t\tcommit_message \"$cur_sha1\"\n+\tdone\n+}\n+\n+peek_next_command () {\n+\tsed -n -e '/^#/d' -e '1s/ .*$//p' <\"$TODO\"\n+}\n+\n+# If $1 is a mark, make a ref from it; otherwise keep it.\n+# Note on marks:\n+#  * :0 is allowed\n+#  * :01 is the same as :1\n+mark_to_ref () {\n+\targ=\"$1\"\n+\tref=$(expr \"x$arg\" : 'x:0*\\([0-9][0-9]*\\)$')\n+\ttest -n \"$ref\" &&\n+\t\targ=\"$MARK_PREFIX/$ref\"\n+\tprintf '%s\\n' \"$arg\"\n+}\n+\n+mark_to_commit () {\n+\tgit rev-parse --verify \"$(mark_to_ref \"$1\")\"\n+}\n+\n+\n+cannot_fallback () {\n+\techo \"$1\"\n+\tdie_to_continue 'Cannot fall back to three-way merge. Please hand-edit.'\n+}\n+\n+\n+fallback_3way () {\n+\tO_OBJECT=$(cd \"$GIT_OBJECT_DIRECTORY\" && pwd)\n+\n+\trm -fr \"$PATCH-merge-\"*\n+\tmkdir \"$PATCH-merge-tmp-dir\"\n+\n+\t# First see if the patch records the index info that we can use.\n+\tgit apply --build-fake-ancestor \"$PATCH-merge-tmp-index\" \"$PATCH\" &&\n+\tGIT_INDEX_FILE=\"$PATCH-merge-tmp-index\" \\\n+\t\tgit write-tree >\"$PATCH-merge-base+\" ||\n+\tcannot_fallback 'Repository lacks necessary blobs to fall back on 3-way merge.'\n+\n+\techo 'Using index info to reconstruct a base tree...'\n+\tif GIT_INDEX_FILE=\"$PATCH-merge-tmp-index\" \\\n+\t\tgit apply --cached \"$PATCH\"\n+\tthen\n+\t\tmv \"$PATCH-merge-base+\" \"$PATCH-merge-base\"\n+\t\tmv \"$PATCH-merge-tmp-index\" \"$PATCH-merge-index\"\n+\telse\n+\t\tcannot_fallback \"Did you hand edit your patch?\n+It does not apply to blobs recorded in its index.\"\n+\tfi\n+\n+\ttest -f \"$PATCH-merge-index\" &&\n+\this_tree=$(GIT_INDEX_FILE=\"$PATCH-merge-index\" git write-tree) &&\n+\torig_tree=$(cat \"$PATCH-merge-base\") &&\n+\trm -fr \"$PATCH-merge-\"* || exit 1\n+\n+\techo 'Falling back to patching base and 3-way merge...'\n+\n+\t# This is not so wrong.  Depending on which base we picked,\n+\t# orig_tree may be wildly different from ours, but his_tree\n+\t# has the same set of wildly different changes in parts the\n+\t# patch did not touch, so recursive ends up canceling them,\n+\t# saying that we reverted all those changes.\n+\n+\teval GITHEAD_$his_tree='\"$firstline\"'\n+\texport GITHEAD_$his_tree\n+\tgit-merge-recursive \"$orig_tree\" -- HEAD \"$his_tree\" || {\n+\t\tgit rerere\n+\t\tdie 'Failed to merge in the changes.'\n+\t}\n+}\n+\n+# Run hook \"$@\" (with arguments) if executable\n+run_hook () {\n+\ttest -z \"$1\" || return\n+\thookname=\"$1\"\n+\thook=\"$GIT_DIR/hooks/$hookname\"\n+\tshift\n+\tif test -x \"$hook\"\n+\tthen\n+\t\t\"$hook\" \"$@\" ||\n+\t\t\tdie_to_continue \"Hook $hookname failed.\"\n+\tfi\n+}\n+\n+# Add Signed-off-by: line if general option --signoff is given\n+dashdash_signoff () {\n+\tadd_signoff=\n+\tif test -n \"$SIGNOFF\"\n+\tthen\n+\t\tlast_signed_off_by=$(\n+\t\t\tsed -n -e '/^Signed-off-by: /p' <\"$MSG\" | sed -n -e '$p'\n+\t\t)\n+\t\ttest \"$last_signed_off_by\" = \"$SIGNOFF\" ||\n+\t\t\tadd_signoff=$(\n+\t\t\t\ttest '' = \"$last_signed_off_by\" && echo\n+\t\t\t\techo \"$SIGNOFF\"\n+\t\t\t)\n+\tfi\n+\t{\n+\t\ttest -s \"$MSG\" && cat \"$MSG\"\n+\t\ttest -n \"$add_signoff\" && echo \"$add_signoff\"\n+\t} >\"$MSG.new\"\n+\tmv \"$MSG.new\" \"$MSG\"\n+}\n+\n+\n+### --caller-related functions\n+\n+# Show string for caller invocation for --abort/--continue/--skip\n+print_caller_info () {\n+\tcase \"$1\" in\n+\t--abort)\n+\t\techo \"$CALLER_ABRT\"\n+\t\t;;\n+\t--continue)\n+\t\techo \"$CALLER_CONT\"\n+\t\t;;\n+\t--skip)\n+\t\techo \"$CALLER_SKIP\"\n+\t\t;;\n+\t*)\n+\t\twarn 'Internal error: Unknown print_caller argument!'\n+\t\t;;\n+\tesac\n+}\n+\n+# Print the program to invoke to (--)abort/continue/skip\n+print_caller() {\n+\tcaller_info=$(print_caller_info \"$1\")\n+\tif test -n \"$CALLERCOMPARE\" -a -n \"$caller_info\"\n+\tthen\n+\t\ttest -n \"$CALLER\" && printf \"$CALLER \"\n+\t\techo \"$caller_info\"\n+\telse\n+\t\techo \"git sequencer $1\"\n+\tfi\n+}\n+\n+# Test if --caller was set correctly\n+# $1 must be abort/continue/skip\n+test_caller () {\n+\tcaller_info=$(print_caller_info \"--$1\")\n+\ttest -n \"$CALLERCOMPARE\" -a \\\n+\t\t\"$CALLERCOMPARE\" != \"$CALLERSTRING\" -a \\\n+\t\t-n \"$caller_info\" &&\n+\t\tdie \"You must use '$CALLER $caller_info' to $1!\"\n+}\n+\n+# Generate $CALLER_SCRIPT file from \"git foo|--abort|--continue|--skip\"\n+# string $1\n+generate_caller_script () {\n+\techo \"$1\" | sed -e 's/^\\(.*\\)|\\(.*\\)|\\(.*\\)|\\(.*\\)$/\\\n+CALLERCOMPARE=\"\\0\"\\\n+CALLER=\"\\1\"\\\n+CALLER_ABRT=\"\\2\"\\\n+CALLER_CONT=\"\\3\"\\\n+CALLER_SKIP=\"\\4\"/' >\"$CALLER_SCRIPT\"\n+}\n+\n+# Run caller script and set GIT_CHERRY_PICK_HELP\n+assure_caller () {\n+\ttest -r \"$CALLER_SCRIPT\" &&\n+\t\t. \"$CALLER_SCRIPT\"\n+\n+\tGIT_CHERRY_PICK_HELP=\"\n+After resolving the conflicts, mark the corrected paths with\n+\tgit add <paths>\n+or\n+\tgit rm <paths>\n+and run\n+\t$(print_caller --continue)\n+Note, that your working tree must match the index.\"\n+\texport GIT_CHERRY_PICK_HELP\n+}\n+\n+\n+### Helpers for check_* functions:\n+\n+# Print a warning on todo checking\n+todo_warn () {\n+\tprintf 'Warning at line %d, %s: %s\\n' \"$line\" \"$command\" \"$*\"\n+}\n+\n+# Raise an error on todo checking\n+todo_error () {\n+\tprintf 'Error at line %d, %s: %s\\n' \"$line\" \"$command\" \"$*\"\n+\tretval=1\n+}\n+\n+# Test if $1 is a commit on todo checking\n+commit_check () {\n+\ttest \"$(git cat-file -t \"$1\")\" = commit ||\n+\t\ttodo_error \"'$1' is not a commit.\"\n+}\n+\n+# A helper function to check if $1 is a an available mark during check_*\n+arg_is_mark_check () {\n+\tfor cur_mark in $available_marks\n+\tdo\n+\t\ttest \"$cur_mark\" -eq \"${1#:}\" && return\n+\tdone\n+\ttodo_error \"Mark $1 is not yet defined.\"\n+}\n+\n+# A helper function for check_* and mark usage:\n+# check if \"$1\" is a commit or a defined mark\n+arg_is_mark_or_commit_check () {\n+\tif expr \"x$1\" : 'x:[0-9][0-9]*$' >/dev/null\n+\tthen\n+\t\targ_is_mark_check \"$1\"\n+\telse\n+\t\tcommit_check \"$1\"\n+\tfi\n+}\n+\n+\n+### Author script functions\n+\n+# Take \"Name <e-mail>\" in stdin and outputs author script\n+make_author_script_from_string () {\n+\tsed -e \"s/'/'\"'\\\\'\"''/g\" \\\n+\t    -e 's/^\\(.*\\) <\\(.*\\)>.*$/GIT_AUTHOR_NAME='\\''\\1'\\''\\\n+GIT_AUTHOR_EMAIL='\\''\\2'\\''\\\n+GIT_AUTHOR_DATE=/'\n+}\n+\n+\n+### General option functions (and options spec)\n+\n+OPTIONS_GENERAL=' General options:\n+author= Override author\n+C,reuse-commit= Reuse message and authorship data from commit\n+F,file= Take commit message from given file\n+m,message= Specify commit message\n+M,reuse-message= Reuse message from commit\n+signoff Add signoff\n+e,edit Invoke editor to edit commit message'\n+\n+# Check if option is a general option\n+check_general_option () {\n+\tgeneral_shift=1\n+\tcase \"$1\" in\n+\t--signoff)\n+\t\treturn 0\n+\t\t;;\n+\t--author)\n+\t\tgeneral_shift=2\n+\t\tauthor_opt=\"t$author_opt\"\n+\t\texpr \"x$2\" : 'x.* <.*>' >/dev/null ||\n+\t\t\ttodo_error \"Author \\\"$2\\\" not in the correct format \\\"Name <e-mail>\\\".\"\n+\t\t;;\n+\t-m)\n+\t\tgeneral_shift=2\n+\t\tmsg_opt=\"t$msg_opt\"\n+\t\t;;\n+\t-C)\n+\t\tgeneral_shift=2\n+\t\tmsg_opt=\"t$msg_opt\"\n+\t\tauthor_opt=\"t$author_opt\"\n+\t\tcommit_check \"$2\"\n+\t\t;;\n+\t-M)\n+\t\tgeneral_shift=2\n+\t\tmsg_opt=\"t$msg_opt\"\n+\t\tcommit_check \"$2\"\n+\t\t;;\n+\t-F)\n+\t\tgeneral_shift=2\n+\t\tmsg_opt=\"t$msg_opt\"\n+\t\ttest -r \"$2\" ||\n+\t\t\ttodo_error \"Cannot read file '$2'.\"\n+\t\t;;\n+\t-e)\n+\t\ttest -z \"$BATCHMODE\" ||\n+\t\t\ttodo_error '--batch and --edit options do not make sense together.'\n+\t\t;;\n+\t*)\n+\t\treturn 1\n+\t\t;;\n+\tesac\n+}\n+\n+# Set a general option variable or return 1\n+handle_general_option () {\n+\tgeneral_shift=1\n+\tcase \"$1\" in\n+\t--signoff)\n+\t\tSIGNOFF=$(git-var GIT_COMMITTER_IDENT | sed -e '\n+\t\t\t\ts/>.*/>/\n+\t\t\t\ts/^/Signed-off-by: /')\n+\t\t;;\n+\t--author)\n+\t\tgeneral_shift=2\n+\t\tAUTHOR=t\n+\t\techo \"$2\" |\n+\t\t\tmake_author_script_from_string >\"$AUTHOR_SCRIPT\"\n+\t\t;;\n+\t-m)\n+\t\tgeneral_shift=2\n+\t\tMESSAGE=\"$2\"\n+\t\t;;\n+\t-C)\n+\t\tgeneral_shift=2\n+\t\tAUTHOR=t\n+\t\tget_author_ident_from_commit \"$2\" >\"$AUTHOR_SCRIPT\"\n+\t\tMESSAGE=$(commit_message \"$2\")\n+\t\t;;\n+\t-M)\n+\t\tgeneral_shift=2\n+\t\tMESSAGE=$(commit_message \"$2\")\n+\t\t;;\n+\t-F)\n+\t\tgeneral_shift=2\n+\t\tMESSAGE=$(cat \"$2\")\n+\t\t;;\n+\t-e)\n+\t\tEDIT=--edit\n+\t\t;;\n+\t*)\n+\t\treturn 1\n+\t\t;;\n+\tesac\n+}\n+\n+\n+### Functions for checking and realizing TODO instructions\n+# Note that options_*, check_* and insn_* function names are reserved.\n+\n+options_pause=\"\\\n+pause\n+--\n+\"\n+\n+# Check the \"pause\" instruction\n+check_pause () {\n+\tshift\n+\ttest -z \"$BATCHMODE\" ||\n+\t\ttodo_error '\"pause\" instruction and --batch do not make sense together.'\n+\ttest $# -eq 0 ||\n+\t\ttodo_error 'The pause instruction takes no arguments.'\n+\treturn 0\n+}\n+\n+# Realize the \"pause\" instruction\n+insn_pause () {\n+\tmark_action_done\n+\tmake_patch HEAD\n+\tif test \"$VERBOSE\" -gt 0\n+\tthen\n+\t\twarn\n+\t\twarn 'You can now edit files and add them to the index.'\n+\t\twarn 'Once you are satisfied with your changes, run'\n+\t\twarn\n+\t\twarn \"\t$(print_caller --continue)\"\n+\t\twarn\n+\t\twarn 'If you only want to change the commit message, run'\n+\t\twarn 'git commit --amend before.'\n+\tfi\n+\techo 'pause' >\"$WHY_FILE\"\n+\texit 2\n+}\n+\n+\n+options_patch=\"\\\n+patch [options] <file>\n+--\n+3,3way Fall back to 3-way merge\n+k Pass to git-mailinfo (keep subject)\n+n Pass to git-mailinfo (no utf8)\n+$OPTIONS_GENERAL\n+ Options passed to git-apply:\n+R,reverse Reverse changes\n+context= Ensure context of ... lines\n+p= Remove ... leading slashes\n+unidiff-zero Bypass unidiff checks\n+exclude= Do not apply changes to given files\n+no-add Ignore additions of patch\n+whitespace= Set whitespace error behavior\n+inaccurate-eof Support inaccurate EOFs\n+u no-op (backward compatibility)\n+binary no-op (backward compatibility)\n+\"\n+\n+# Check the \"file\" instruction\n+check_patch () {\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-3|-k|-n|-u|--binary|-R|--reverse|--unidiff-zero|--no-add|--inaccurate-eof)\n+\t\t\t:\n+\t\t\t;;\n+\t\t-p|--whitespace|--exclude|--context)\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\tcheck_general_option \"$@\" ||\n+\t\t\t\ttodo_warn \"Unknown option $1\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\t\t\tbreak\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tif test -f \"$1\" -a -r \"$1\"\n+\tthen\n+\t\tgrep -e '^diff' \"$1\" >/dev/null ||\n+\t\t\ttodo_error \"File '$1' contains no patch.\"\n+\telse\n+\t\ttodo_error \"Cannot open file '$1'.\"\n+\tfi\n+\treturn 0\n+}\n+\n+# Realize the \"patch\" instruction\n+insn_patch () {\n+\tcomment_for_reflog patch\n+\n+\tapply_opts=\n+\tmailinfo_opts=\n+\tthreeway=\n+\n+\t# temporary files\n+\tinfofile=\"$SEQ_DIR/patch-info\"\n+\tmsgfile=\"$SEQ_DIR/patch-msg\"\n+\n+\twhile test \"$#\" -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-3)\n+\t\t\tthreeway=t\n+\t\t\t;;\n+\t\t-k|-n)\n+\t\t\tmailinfo_opts=\"$mailinfo_opts $1\"\n+\t\t\t;;\n+\t\t-u|--binary)\n+\t\t\t: Do nothing. It is there due to b/c only.\n+\t\t\t;;\n+\t\t-R|--reverse|--unidiff-zero|--no-add|--inaccurate-eof)\n+\t\t\tapply_opts=\"$apply_opts $1\"\n+\t\t\t;;\n+\t\t-p)\n+\t\t\tshift\n+\t\t\tapply_opts=\"$apply_opts -p$1\"\n+\t\t\t;;\n+\t\t--whitespace|--exclude)\n+\t\t\tapply_opts=\"$apply_opts $1=$2\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--context)\n+\t\t\tshift\n+\t\t\tapply_opts=\"$apply_opts -C$1\"\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t*)\n+\t\t\thandle_general_option \"$@\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tfilename=\"$1\"\n+\n+\tmark_action_done\n+\n+\tgit mailinfo $mailinfo_opts \"$msgfile\" \"$PATCH\" \\\n+\t\t<\"$filename\" >\"$infofile\" ||\n+\t\tdie_abort 'Could not read or parse mail'\n+\n+\t# if author not set by option, read author information of patch\n+\tif test -z \"$AUTHOR\"\n+\tthen\n+\t\tcp \"$ORIG_AUTHOR_SCRIPT\" \"$AUTHOR_SCRIPT\"\n+\t\tsed -e \"s/'/'\"'\\\\'\"''/g\" -n -e '\n+\t\t\ts/^Author: \\(.*\\)$/GIT_AUTHOR_NAME='\\''\\1'\\''/p;\n+\t\t\ts/^Email: \\(.*\\)$/GIT_AUTHOR_EMAIL='\\''\\1'\\''/p;\n+\t\t\ts/^Date: \\(.*\\)$/GIT_AUTHOR_DATE='\\''\\1'\\''/p\n+\t\t' <\"$infofile\" >>\"$AUTHOR_SCRIPT\"\n+\t\t# If sed's result is empty, we keep the original\n+\t\t# author script by appending.\n+\tfi\n+\n+\t# Ignore every mail that's not containing a patch\n+\ttest -s \"$PATCH\" || {\n+\t\twarn 'Does not contain patch!'\n+\t\treturn 0\n+\t}\n+\n+\tedit_msg=\n+\tif grep -e '^Subject:' \"$infofile\" >/dev/null\n+\tthen\n+\t\t# add subject to commit message\n+\t\tsed -n -e '/^Subject:/ s/Subject: //p' <\"$infofile\"\n+\t\techo\n+\t\techo\n+\t\tcat \"$msgfile\"\n+\telse\n+\t\tcat \"$msgfile\"\n+\t\tedit_msg=t\n+\tfi | git stripspace >\"$MSG\"\n+\trm -f \"$infofile\" \"$msgfile\"\n+\n+\tfirstline=$(sed -e '1q' <\"$MSG\")\n+\n+\tget_current_author\n+\n+\ttest -n \"$MESSAGE\" && printf '%s\\n' \"$MESSAGE\" >\"$MSG\"\n+\ttest -z \"$firstline\" && firstline=$(sed -e '1q' <\"$MSG\")\n+\n+\tdashdash_signoff\n+\n+\twith_author run_hook applypatch-msg \"$MSG\"\n+\tfailed=\n+\tgit apply $apply_opts --index \"$PATCH\" || failed=t\n+\n+\tif test -n \"$failed\" -a -n \"$threeway\" && (with_author fallback_3way)\n+\tthen\n+\t\t# Applying the patch to an earlier tree and merging the\n+\t\t# result may have produced the same tree as ours.\n+\t\tgit diff-index --quiet --cached HEAD -- && {\n+\t\t\techo 'No changes -- Patch already applied.'\n+\t\t\treturn 0\n+\t\t\t# XXX: do we want that?\n+\t\t}\n+\t\t# clear apply_status -- we have successfully merged.\n+\t\tfailed=\n+\tfi\n+\n+\tif test -n \"$failed\"\n+\tthen\n+\t\tdie_to_continue 'Patch failed.'\n+\t\t# XXX: We actually needed a git-apply flag that creates\n+\t\t# conflict markers and sets the DIFF_STATUS_UNMERGED flag.\n+\tfi\n+\n+\twith_author run_hook pre-applypatch\n+\n+\ttest -n \"$EDIT\" && edit_msg=t\n+\tif ! has_message \"$MSG\" || test -n \"$edit_msg\"\n+\tthen\n+\t\techo \"\n+# Please enter the commit message for the applied patch.\n+# (Comment lines starting with '#' will not be included)\" >>\"$MSG\"\n+\n+\t\tgit_editor \"$MSG\" ||\n+\t\t\tdie_with_patch 'Editor returned error.'\n+\t\thas_message \"$MSG\" ||\n+\t\t\tdie_with_patch 'No commit message given.'\n+\tfi\n+\n+\ttree=$(git write-tree) &&\n+\tparent=$(git rev-parse --verify HEAD) &&\n+\tcommit=$(with_author git commit-tree \"$tree\" -p \"$parent\" <\"$MSG\") &&\n+\tgit update-ref -m \"$GIT_REFLOG_ACTION: $firstline\" HEAD \"$commit\" \"$parent\" ||\n+\t\tdie_to_continue 'Could not commit tree.'\n+\n+\ttest -x \"$GIT_DIR/hooks/post-applypatch\" &&\n+\t\twith_author \"$GIT_DIR/hooks/post-applypatch\"\n+\n+\treturn 0\n+}\n+\n+\n+options_pick=\"\\\n+pick [options] <commit>\n+--\n+R,reverse Revert introduced changes\n+mainline= Specify parent number to use for merge commits\n+$OPTIONS_GENERAL\n+\"\n+\n+# Check the \"pick\" instruction\n+check_pick () {\n+\tmainline=\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-R)\n+\t\t\t;;\n+\t\t--mainline)\n+\t\t\tshift\n+\t\t\tmainline=\"$1\"\n+\t\t\ttest \"$mainline\" -gt 0 || {\n+\t\t\t\ttodo_error '--mainline needs an integer beginning from 1.'\n+\t\t\t\tmainline=\n+\t\t\t}\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\tcheck_general_option \"$@\" ||\n+\t\t\t\ttodo_warn \"Unknown option $1\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\t\t\tbreak\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tif test -n \"$mainline\"\n+\tthen\n+\t\tparents=$(count_parents \"$1\")\n+\t\ttest \"$parents\" -lt \"$mainline\" &&\n+\t\t\ttodo_error \"Commit has only $parents (less than $mainline) parents.\"\n+\t\ttest \"$parents\" -eq 1 &&\n+\t\t\ttodo_warn 'Commit is not a merge at all.'\n+\tfi\n+\n+\tcommit_check \"$1\"\n+\n+\treturn 0\n+}\n+\n+# Realize the \"pick\" instruction\n+insn_pick () {\n+\top=cherry-pick\n+\tmainline=\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-R)\n+\t\t\top=revert\n+\t\t\t;;\n+\t\t--mainline)\n+\t\t\tmainline=\"$1 $2\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\thandle_general_option \"$@\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tsha1=$(git rev-parse --verify \"$1\")\n+\n+\tcomment_for_reflog pick\n+\n+\tmark_action_done\n+\n+\tedit_msg=\"$EDIT\"\n+\n+\t# Don't edit on pick, but later, if author or message given.\n+\ttest -n \"$AUTHOR\" -o -n \"$MESSAGE\" && edit_msg=\n+\n+\t# Be kind to users and ignore --mainline=1 on non-merge commits\n+\ttest -n \"$mainline\" -a 2 -gt $(count_parents \"$sha1\") && mainline=\n+\n+\tuse_perform=\n+\ttest -n \"$edit_msg\" ||\n+\t\tuse_perform=perform\n+\n+\tpick_one \"$op\" $edit_msg $mainline $sha1 ||\n+\t\tdie_with_patch $sha1 \"Could not apply $sha1\"\n+\n+\ttest -n \"$EDIT\" ||\n+\t\tuse_perform=perform\n+\n+\tget_current_author\n+\tsignoff=\n+\ttest -n \"$SIGNOFF\" && signoff=-s\n+\tif test -n \"$AUTHOR\" -a -n \"$MESSAGE\"\n+\tthen\n+\t\t# this is just because we only want to do ONE amending commit\n+\t\t$use_perform git commit --amend $EDIT $signoff --no-verify \\\n+\t\t\t--author \"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\" \\\n+\t\t\t--message=\"$MESSAGE\"\n+\telif test -n \"$AUTHOR\"\n+\tthen\n+\t\t# correct author if AUTHOR is set\n+\t\t$use_perform git commit --amend $EDIT --no-verify -C HEAD \\\n+\t\t\t--author \"$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>\"\n+\telif test -n \"$MESSAGE\"\n+\tthen\n+\t\t# correct commit message if MESSAGE is set\n+\t\t$use_perform git commit --amend $EDIT $signoff --no-verify \\\n+\t\t\t-C HEAD --message=\"$MESSAGE\"\n+\telif test -n \"$SIGNOFF\"\n+\tthen\n+\t\t# only add signoff\n+\t\t$use_perform git commit --amend $EDIT $signoff --no-verify \\\n+\t\t\t-C HEAD\n+\tfi\n+\n+\treturn 0\n+}\n+\n+options_edit=\"\\\n+edit <commit>\n+--\n+\"\n+\n+# Check the \"edit\" instruction\n+check_edit () {\n+\tshift\n+\ttest -z \"$BATCHMODE\" ||\n+\t\ttodo_error '\"edit\" instruction and --batch do not make sense together.'\n+\ttest $# -eq 1 ||\n+\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\treturn 0\n+}\n+\n+# Realize the \"edit\" instruction\n+insn_edit () {\n+\tshift\n+\tinsn_pick \"$1\"\n+\n+\t# work around mark_action_done in insn_pause\n+\techo '# pausing' >\"$TODO.new\"\n+\tcat \"$TODO\" >>\"$TODO.new\"\n+\tmv -f \"$TODO.new\" \"$TODO\"\n+\tinsn_pause\n+}\n+\n+\n+options_squash=\"\\\n+squash <commit>\n+squash [options] --from <mark>\n+--\n+from Squash all commits from <mark>\n+collect-signoffs Collect Signed-off-by: lines\n+include-merges Do not fail on merge commits\n+$OPTIONS_GENERAL\n+\"\n+\n+# Check the \"squash\" instruction\n+check_squash () {\n+\tfrom=\n+\tcollect=\n+\tmerges=\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t--from)\n+\t\t\tfrom=t\n+\t\t\t;;\n+\t\t--collect-signoffs)\n+\t\t\tcollect=t\n+\t\t\ttodo_warn 'Not yet implemented.'\n+\t\t\t;;\n+\t\t--include-merges)\n+\t\t\tmerges=t\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t*)\n+\t\t\tcheck_general_option \"$@\" ||\n+\t\t\t\ttodo_error \"Unknown option $1\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\t# in --from mode?\n+\tif test -n \"$from\"\n+\tthen\n+\t\ttest -z \"$merges\" &&\n+\t\t\tcat \"$DONE\" \"$TODO\" |\n+\t\t\tsed -n -e '/^[ \\t]*mark[ \\t]*:\\{0,1\\}'\"${1#:}\"'\\($\\|[^0-9]\\)/,'\"$line\"'p' |\n+\t\t\tgrep '^[ \\t]*merge' >/dev/null &&\n+\t\t\ttodo_error \"$1..HEAD contains a merge commit. You may try --include-merges.\"\n+\n+\t\targ_is_mark_check \"$1\"\n+\telse\n+\t\ttest -n \"$merges\" &&\n+\t\t\ttodo_error '--include-merges only makes sense with --from <mark>.'\n+\t\ttest -n \"$collect\" &&\n+\t\t\ttodo_error '--collect-signoffs only makes sense with --from <mark>.'\n+\n+\t\tcommit_check \"$1\"\n+\tfi\n+\n+\treturn 0\n+}\n+\n+# Realize the \"squash\" instruction\n+insn_squash () {\n+\tsquash_msg=\"$MSG-squash\"\n+\tfrom=\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t--from)\n+\t\t\tfrom=t\n+\t\t\t;;\n+\t\t--collect-signoffs)\n+\t\t\twarn '--collect-signoffs is not implemented.'\n+\t\t\t# XXX\n+\t\t\t;;\n+\t\t--include-merges)\n+\t\t\t: # This has to be done during check_squash\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t*)\n+\t\t\thandle_general_option \"$@\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tif test -n \"$from\"\n+\tthen\n+\t\tsha1=$(mark_to_commit \":${1#:}\")\n+\telse\n+\t\tsha1=$(git rev-parse --verify \"$1\")\n+\tfi\n+\n+\tcomment_for_reflog squash\n+\n+\t# Hm, somehow I don't think --skip on a conflicting squash\n+\t# may be useful, but if someone wants to do it, it should\n+\t# do the obvious: skip what squash would do.\n+\techo \"$(git rev-parse HEAD)\" >\"$SEQ_DIR/skiphead\"\n+\n+\tmark_action_done\n+\n+\tif test -n \"$MESSAGE\"\n+\tthen\n+\t\tprintf '%s\\n' \"$MESSAGE\" >\"$MSG\"\n+\telse\n+\t\tif test -n \"$from\"\n+\t\tthen\n+\t\t\tmake_squash_message_multiple \"$sha1\" >\"$MSG\"\n+\t\telse\n+\t\t\tmake_squash_message \"$sha1\" >\"$MSG\"\n+\t\tfi\n+\tfi\n+\n+\tcase \"$(peek_next_command)\" in\n+\tsquash)\n+\t\tedit_commit=\n+\t\tuse_perform=perform\n+\t\tcp \"$MSG\" \"$squash_msg\"\n+\t\t;;\n+\t*)\n+\t\tedit_commit=-e\n+\t\tuse_perform=\n+\t\trm -f \"$squash_msg\" || exit\n+\t\t;;\n+\tesac\n+\n+\ttest -n \"$MESSAGE\" && edit_commit=\n+\ttest -n \"$EDIT\" && edit_commit=-e\n+\n+\t# is --author (or equivalent) set?\n+\tif test -n \"$AUTHOR\"\n+\tthen\n+\t\t# evaluate author script\n+\t\tget_current_author\n+\telse\n+\t\t# if --author is not given, we get the authorship\n+\t\t# information from the commit before.\n+\t\teval \"$(get_author_ident_from_commit HEAD)\"\n+\t\t# but we do not write an author script\n+\tfi\n+\n+\t# --from or not\n+\tfailed=\n+\tif test -n \"$from\"\n+\tthen\n+\t\tperform git reset --soft \"$sha1\"\n+\telse\n+\t\tperform git reset --soft HEAD^\n+\n+\t\tpick_one cherry-pick -n \"$sha1\" || failed=t\n+\tfi\n+\n+\tdashdash_signoff\n+\n+\tif test -z \"$failed\"\n+\tthen\n+\t\t# This is like --amend, but with a different message\n+\t\twith_author $use_perform git commit --no-verify \\\n+\t\t\t-F \"$MSG\" $edit_commit || failed=t\n+\telse\n+\t\tcp \"$MSG\" \"$GIT_DIR/MERGE_MSG\"\n+\t\twarn\n+\t\twarn \"Could not apply $sha1...\"\n+\t\tdie_with_patch $sha1 \"\"\n+\tfi\n+\n+\treturn 0\n+}\n+\n+\n+options_mark=\"\\\n+mark <mark>\n+--\n+\"\n+\n+# Check the \"mark\" instruction\n+check_mark () {\n+\tshift\n+\ttest $# -eq 1 ||\n+\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\tmy_mark=$(expr \"x${1#:}\" : 'x0*\\([0-9][0-9]*\\)$')\n+\ttest -n \"$my_mark\" ||\n+\t\ttodo_error \"Mark $1 not an integer.\"\n+\texpr \"x$available_marks \" : \" $my_mark \" >/dev/null &&\n+\t\ttodo_error \"Mark :$my_mark already defined. Choose another integer.\"\n+\tavailable_marks=\"$available_marks $my_mark\"\n+\n+\treturn 0\n+}\n+\n+# Realize the \"mark\" instruction\n+insn_mark () {\n+\tshift\n+\tgiven=\"$1\"\n+\n+\tmark_action_done\n+\n+\tmark=$(mark_to_ref \":${given#:}\")\n+\tgit update-ref \"$mark\" HEAD\n+\treturn 0\n+}\n+\n+\n+options_merge=\"\\\n+merge [options] <commit-ish> ...\n+--\n+standard Generate default commit message\n+s,strategy= Use merge strategy ...\n+$OPTIONS_GENERAL\n+\"\n+\n+# Check the \"merge\" instruction\n+check_merge () {\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t--standard)\n+\t\t\tmsg_opt=\"t$msg_opt\"\n+\t\t\t;;\n+\t\t-s)\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\tcheck_general_option \"$@\" ||\n+\t\t\t\ttodo_error \"Unknown option $1\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\ttest $# -gt 0 ||\n+\t\ttodo_error 'What are my parents? Need new parents!'\n+\n+\twhile test $# -gt 0\n+\tdo\n+\t\targ_is_mark_or_commit_check \"$1\"\n+\t\tshift\n+\tdone\n+\treturn 0\n+}\n+\n+# Realize the \"merge\" instruction\n+insn_merge () {\n+\tcomment_for_reflog merge\n+\n+\tstandard=\n+\n+\twhile test $# -gt 1\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t--standard)\n+\t\t\tstandard=t\n+\t\t\t;;\n+\t\t-s)\n+\t\t\tshift\n+\t\t\tstrategy=\"-s $1\"\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\thandle_general_option \"$@\"\n+\t\t\t;;\n+\t\tesac\n+\t\tshift $general_shift\n+\tdone\n+\n+\tnew_parents=\n+\tfor p in \"$@\"\n+\tdo\n+\t\tnew_parents=\"$new_parents $(mark_to_ref $p)\"\n+\tdone\n+\tnew_parents=\"${new_parents# }\"\n+\n+\tget_current_author\n+\n+\tif test -n \"$standard\"\n+\tthen\n+\t\tfor cur_parent in $new_parents\n+\t\tdo\n+\t\t\tprintf '%s\\t\\t%s' \\\n+\t\t\t\t\"$(git rev-parse \"$cur_parent\")\" \"$cur_parent\"\n+\t\tdone | git fmt-merge-msg >\"$MSG\"\n+\tfi\n+\n+\ttest -n \"$MESSAGE\" &&\n+\t\tprintf '%s\\n' \"$MESSAGE\" >\"$MSG\"\n+\n+\tdashdash_signoff\n+\tif ! has_message \"$MSG\" || test -n \"$EDIT\"\n+\tthen\n+\t\techo \"\n+# Please enter the merge commit message.\n+# (Comment lines starting with '#' will not be included)\" >>\"$MSG\"\n+\n+\t\tgit_editor \"$MSG\" ||\n+\t\t\tdie_with_patch 'Editor returned error.'\n+\t\thas_message \"$MSG\" ||\n+\t\t\tdie_with_patch 'No commit message given.'\n+\tfi\n+\n+\tmark_action_done\n+\tif ! with_author perform git merge $strategy -m junk $new_parents\n+\tthen\n+\t\tgit rerere\n+\t\tcp \"$MSG\" \"$GIT_DIR/MERGE_MSG\"\n+\t\tdie_to_continue 'Error merging'\n+\tfi\n+\twith_author perform git commit --amend -F \"$MSG\" --no-verify\n+\treturn 0\n+}\n+\n+\n+options_reset=\"\\\n+reset <commit-ish>\n+--\n+\"\n+\n+# Check the \"reset\" instruction\n+check_reset () {\n+\tshift\n+\ttest $# -eq 1 ||\n+\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\targ_is_mark_or_commit_check \"$1\"\n+\n+\treturn 0\n+}\n+\n+# Realize the \"reset\" instruction\n+insn_reset () {\n+\tshift\n+\tcomment_for_reflog reset\n+\n+\tmark_action_done\n+\tperform git reset --hard \"$(mark_to_commit \"$1\")\"\n+}\n+\n+\n+options_ref=\"\\\n+ref <ref>\n+--\n+\"\n+\n+# Check the \"ref\" instruction\n+check_ref () {\n+\tshift\n+\ttest $# -eq 1 ||\n+\t\ttodo_error \"Wrong number of arguments. ($# given, 1 wanted)\"\n+\treturn 0\n+}\n+\n+# Realize the \"ref\" instruction\n+insn_ref () {\n+\tshift\n+\tcomment_for_reflog ref\n+\n+\tmark_action_done\n+\tperform git update-ref \"$1\" HEAD\n+}\n+\n+\n+### Instruction main loop\n+\n+# Run check_* or insn_* with massaged options\n+# Usage: run_insn (check|do) <insn> <insn options>\n+run_insn () {\n+\tc_or_i=\"$1\"\n+\tinsn=\"$2\"\n+\tshift\n+\tshift\n+\teval \"option_spec=\\\"\\$options_$insn\\\"\"\n+\teval \"$(printf \"%s\" \"$option_spec\" |\n+\t\tgit rev-parse --parseopt -- \"$@\" ||\n+\t\techo return)\"\n+\tcase \"$c_or_i\" in\n+\tcheck)\n+\t\tcheck_$insn \"$@\"\n+\t\t;;\n+\tdo)\n+\t\tinsn_$insn \"$@\"\n+\t\t;;\n+\tesac\n+}\n+\n+# Execute the first line of the current TODO file\n+execute_next () {\n+\trm -f \"$MSG\"\n+\techo 'HEAD' >\"$SEQ_DIR/skiphead\"\n+\tread command rol <\"$TODO\"\n+\tcase \"$command\" in\n+\t'#'*|'')\n+\t\tmark_action_done\n+\t\t;;\n+\t*)\n+\t\ttest \"$VERBOSE\" -gt 1 &&\n+\t\t\techo \"Next line: $command $rol\"\n+\n+\t\t# reset general options\n+\t\trm -f \"$AUTHOR_SCRIPT\"\n+\t\tgeneral_shift=1\n+\t\tAUTHOR=\n+\t\tEDIT=\n+\t\tMESSAGE=\n+\t\tSIGNOFF=\n+\t\t# XXX: eval is evil!\n+\t\teval \"run_insn do $command $rol\" ||\n+\t\t\tdie_to_continue 'An unexpected error occured.'\n+\t\t;;\n+\tesac\n+}\n+\n+# Execute the rest of the TODO file and finish\n+execute_rest () {\n+\twhile has_action \"$TODO\"\n+\tdo\n+\t\texecute_next\n+\tdone\n+\n+\tcomment_for_reflog finish\n+\tif test -n \"$ONTO\"\n+\tthen\n+\t\tgit update-ref -m \"$GIT_REFLOG_ACTION: $ONTO\" \"$ONTO\" HEAD &&\n+\t\tgit symbolic-ref HEAD \"$ONTO\"\n+\tfi &&\n+\tquit\n+}\n+\n+\n+# Main loop to check instructions\n+todo_check () {\n+\ttodo=\"$TODO\"\n+\ttest -n \"$1\" && todo=\"$1\"\n+\n+\tavailable_marks=' '\n+\tfor cur_mark in $(git for-each-ref --format='%(refname)' \"$MARK_PREFIX\")\n+\tdo\n+\t\tavailable_marks=\"$available_marks ${cur_mark##*/}\"\n+\tdone\n+\n+\tretval=0\n+\tline=1\n+\twhile read command rol\n+\tdo\n+\t\tcase \"$command\" in\n+\t\t'#'*|'')\n+\t\t\t;;\n+\t\t*)\n+\t\t\teval 'test -n \"$options_'\"$command\"'\"' || {\n+\t\t\t\tretval=1\n+\t\t\t\ttodo_error \"Unknown $command instruction\"\n+\t\t\t\tcontinue\n+\t\t\t}\n+\n+\t\t\tgeneral_shift=1\n+\t\t\tmsg_opt=\n+\t\t\tauthor_opt=\n+\t\t\teval \"run_insn check $command $rol\" ||\n+\t\t\t\ttodo_error \"Unknown option used\"\n+\t\t\texpr \"$msg_opt\" : 'ttt*' >/dev/null &&\n+\t\t\t\ttodo_error 'You can only provide one commit message option.'\n+\t\t\texpr \"$author_opt\" : 'ttt*' >/dev/null &&\n+\t\t\t\ttodo_error 'You can only provide one author option.'\n+\t\t\t;;\n+\t\tesac\n+\t\tline=$(expr \"$line\" + 1)\n+\tdone <\"$todo\"\n+\treturn $retval\n+}\n+\n+prepare_editable_todo () {\n+\techo '# ALREADY DONE:'\n+\tsed -e 's/^/#  /' <\"$DONE\"\n+\techo '# '\n+\techo \"$markline\"\n+\tcat \"$TODO\"\n+}\n+\n+get_saved_options () {\n+\tread VERBOSE <\"$SEQ_DIR/verbose\"\n+\tread ONTO <\"$SEQ_DIR/onto\"\n+\ttest -f \"$WHY_FILE\" &&\n+\t\tread WHY <\"$WHY_FILE\"\n+\treturn 0\n+}\n+\n+# Realize sequencer invocation\n+do_startup () {\n+\ttest -d \"$SEQ_DIR\" &&\n+\t\tdie 'sequencer already started'\n+\n+\trequire_clean_work_tree\n+\n+\tHEAD=$(git rev-parse --verify HEAD) ||\n+\t\tdie 'No HEAD?'\n+\n+\tmkdir \"$SEQ_DIR\" ||\n+\t\tdie \"Could not create temporary $SEQ_DIR\"\n+\n+\t# save options\n+\techo \"$VERBOSE\" >\"$SEQ_DIR/verbose\"\n+\ttest -n \"$CALLERSTRING\" &&\n+\t\tgenerate_caller_script \"$CALLERSTRING\"\n+\t# generate empty DONE and \"onto\" file\n+\t: >\"$DONE\"\n+\t: >\"$SEQ_DIR/onto\"\n+\n+\tif test -n \"$BATCHMODE\"\n+\tthen\n+\t\tGIT_CHERRY_PICK_HELP='  Aborting (batch mode)'\n+\t\texport GIT_CHERRY_PICK_HELP\n+\telse\n+\t\tassure_caller\n+\tfi\n+\n+\tcomment_for_reflog start\n+\n+\t# save old head before checking out the given <branch>\n+\tgit symbolic-ref HEAD >\"$SEQ_DIR/head-name\" 2>/dev/null ||\n+\t\techo 'detached HEAD' >\"$SEQ_DIR/head-name\"\n+\techo $HEAD >\"$SEQ_DIR/head\"\n+\t# do it here so that die_abort can work ;)\n+\n+\tif test -n \"$ONTO\"\n+\tthen\n+\t\t# if ONTO is a branch name, then keep it, otherwise\n+\t\t# we don't care anymore and erase ONTO.\n+\t\tif git-show-ref --quiet --verify -- \"refs/heads/${ONTO##*/}\"\n+\t\tthen\n+\t\t\tONTO=\"refs/heads/${ONTO##*/}\"\n+\t\t\techo \"$ONTO\" >\"$SEQ_DIR/onto\"\n+\t\t\tperform git checkout \"$(git rev-parse \"$ONTO\")\" ||\n+\t\t\t\tdie_abort \"Could not checkout branch $ONTO\"\n+\t\telse\n+\t\t\tperform git checkout \"$ONTO\" ||\n+\t\t\t\tdie_abort \"Could not checkout commit $ONTO\"\n+\t\t\tONTO=\n+\t\tfi\n+\tfi\n+\n+\t(git var GIT_AUTHOR_IDENT || git var COMMITTER_IDENT) |\n+\t\tmake_author_script_from_string >\"$ORIG_AUTHOR_SCRIPT\"\n+\n+\t# read from file or from stdin?\n+\tif test -z \"$1\"\n+\tthen\n+\t\t: >\"$TODO\" ||\n+\t\t\tdie_abort \"Could not generate TODO file $TODO\"\n+\t\twhile read line\n+\t\tdo\n+\t\t\tprintf '%s\\n' \"$line\" >>\"$TODO\" ||\n+\t\t\t\tdie_abort \"Could not append to TODO file $TODO\"\n+\t\tdone\n+\telse\n+\t\tcp \"$1\" \"$TODO\" ||\n+\t\t\tdie_abort \"Could not find TODO file $1.\"\n+\tfi\n+\n+\thas_action \"$TODO\" || die_abort 'Nothing to do'\n+\ttodo_check || WHY=todo die_to_continue \"TODO file contains errors.\n+Fix with git sequencer --edit or abort with $(print_caller --abort).\"\n+\n+\texecute_rest\n+\texit\n+}\n+\n+# Realize --continue.\n+do_continue () {\n+\ttest -d \"$SEQ_DIR\" || die 'No sequencer running'\n+\ttest_caller 'continue'\n+\n+\ttodo_check || WHY=todo die_to_continue \"TODO file contains errors.\n+Fix with git sequencer --edit or abort with $(print_caller --abort).\"\n+\n+\tcomment_for_reflog continue\n+\n+\t# Sanity check\n+\tgit rev-parse --verify HEAD >/dev/null ||\n+\t\tdie_to_continue 'Cannot read HEAD'\n+\tgit update-index --ignore-submodules --refresh &&\n+\t\tgit diff-files --quiet --ignore-submodules ||\n+\t\tdie_to_continue 'Working tree is dirty. (Use git add or git stash first?)'\n+\n+\tget_saved_options\n+\n+\t# do we have anything to commit? (staged changes)\n+\tif ! git diff-index --cached --quiet --ignore-submodules HEAD --\n+\tthen\n+\t\tget_current_author\n+\n+\t\t# After \"pause\", we should amend (merge-safe!).\n+\t\t# On conflict, we do not have a commit to amend, so we\n+\t\t# should just commit.\n+\t\tcase \"$WHY\" in\n+\t\tpause)\n+\t\t\twith_author git commit --amend --no-verify -F \"$MSG\" -e ||\n+\t\t\t\tdie_to_continue 'Could not commit staged changes.'\n+\t\t\t;;\n+\t\tconflict)\n+\t\t\twith_author git commit --no-verify -F \"$MSG\" -e ||\n+\t\t\t\tdie_to_continue 'Could not commit staged changes.'\n+\t\t\techo '# resolved CONFLICTS of the last instruction' >>\"$DONE\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\tdie_to_continue 'There are staged changes. Do not know what to do with them.'\n+\t\tesac\n+\tfi\n+\n+\trequire_clean_work_tree\n+\tclean_why\n+\texecute_rest\n+\texit\n+}\n+\n+# Realize --abort.\n+do_abort () {\n+\ttest -d \"$SEQ_DIR\" || die 'No sequencer running'\n+\ttest_caller 'abort'\n+\n+\tcomment_for_reflog abort\n+\trestore\n+\tquit\n+}\n+\n+# Realize --skip.\n+do_skip () {\n+\ttest -d \"$SEQ_DIR\" || die 'No sequencer running'\n+\ttest_caller 'skip'\n+\n+\ttodo_check || WHY=todo die_to_continue \"TODO file contains errors.\n+Fix with git sequencer --edit or abort with $(print_caller --abort).\"\n+\tget_saved_options\n+\n+\tcomment_for_reflog skip\n+\tgit rerere clear\n+\tclean_why\n+\n+\tperform git reset --hard \"$(cat \"$SEQ_DIR/skiphead\")\" &&\n+\techo '# SKIPPED the last instruction' >>\"$DONE\" &&\n+\t\texecute_rest\n+\texit\n+}\n+\n+# Realize --edit.\n+do_edit () {\n+\ttest -d \"$SEQ_DIR\" || die 'No sequencer running'\n+\n+\tmarkline='### BEGIN EDITING BELOW THIS LINE ###'\n+\tprepare_editable_todo >\"$TODO.new\"\n+\n+\t# XXX: does not make sense\n+\t#      when input does not come from a terminal\n+\tgit_editor \"$TODO.new\" ||\n+\t\tdie 'Editor returned an error.'\n+\n+\tif test -t 0 -a -t 1\n+\tthen\n+\t\techo\n+\t\t# interactive:\n+\t\tuntil has_action \"$TODO.new\" && todo_check \"$TODO.new\"\n+\t\tdo\n+\t\t\thas_action \"$TODO.new\" || echo 'TODO file empty.'\n+\t\t\tprintf 'What to do with the file? [c]orrect/[e]dit again/[r]ewind/[s]ave/[?] '\n+\t\t\tread reply\n+\t\t\tcase \"$reply\" in\n+\t\t\t[cC]*)\n+\t\t\t\tgit_editor \"$TODO.new\"\n+\t\t\t\t;;\n+\t\t\t[eE]*)\n+\t\t\t\tprepare_editable_todo >\"$TODO.new\"\n+\t\t\t\tgit_editor \"$TODO.new\"\n+\t\t\t\t;;\n+\t\t\t[rRxXqQ]*)\n+\t\t\t\trm -f \"$TODO.new\"\n+\t\t\t\texit 0\n+\t\t\t\t;;\n+\t\t\t[sS]*)\n+\t\t\t\ttest \"$WHY\" != 'pause' ||\n+\t\t\t\t\techo 'todo' >\"$WHY_FILE\"\n+\t\t\t\tbreak\n+\t\t\t\t;;\n+\t\t\t[?hH]*)\n+\t\t\t\tcat <<EOF\n+\n+Help:\n+s - save TODO file and exit\n+c - respawn editor to correct TODO file\n+e - drop changes and respawn editor on original TODO file\n+r - drop changes and exit as if nothing happened\n+? - print this help\n+EOF\n+\t\t\t\t;;\n+\t\t\tesac\n+\t\t\techo\n+\t\tdone\n+\telse\n+\t\t# defaults:\n+\t\thas_action \"$TODO.new\" || quit \"Nothing to do\"\n+\t\ttodo_check || die 'TODO file contains errors. Aborting.'\n+\tfi\n+\tcp \"$TODO\" \"$TODO.old\"\n+\tif grep \"^$markline\" \"$TODO.new\" >/dev/null\n+\tthen\n+\t\tsed -e \"1,/^$markline/d\" <\"$TODO.new\" >\"$TODO\"\n+\telse\n+\t\tcp \"$TODO.new\" \"$TODO\"\n+\tfi\n+\trm -f \"$TODO.new\"\n+\techo\n+\techo 'TODO file contains:'\n+\techo\n+\tcat \"$TODO\"\n+\texit 0\n+}\n+\n+# Realize --status.\n+do_status () {\n+\ttest -d \"$SEQ_DIR\" || die 'No sequencer running.'\n+\tget_saved_options\n+\n+\tif has_action \"$DONE\"\n+\tthen\n+\t\techo 'Already done:'\n+\t\tsed -e 's/^/  /' <\"$DONE\"\n+\t\techo\n+\tfi\n+\tcase \"$WHY\" in\n+\tpause)\n+\t\techo 'Intentionally paused.'\n+\t\t;;\n+\tconflict)\n+\t\techo 'Interrupted by conflict at'\n+\t\tsed -n -e 's/^/  /;$p' <\"$DONE\"\n+\t\t;;\n+\ttodo)\n+\t\techo 'Interrupted because of errors in the TODO file.'\n+\t\t;;\n+\t*)\n+\t\techo 'Current state is broken.'\n+\tesac\n+\ttest \"$VERBOSE\" -gt 1 && echo 'Running verbosely.'\n+\ttest \"$VERBOSE\" -lt 1 && echo 'Running quietly.'\n+\ttest -n \"$ONTO\" &&\n+\t\techo \"Sequencing on branch ${ONTO##*/}.\"\n+\tif has_action \"$TODO\"\n+\tthen\n+\t\techo\n+\n+\t\techo 'Still to do:'\n+\t\tsed -e 's/^/  /' <\"$TODO\"\n+\tfi\n+\tif test \"$WHY\" = todo\n+\tthen\n+\t\techo\n+\t\techo 'But there are errors. To edit, run:'\n+\t\techo '    git sequencer --edit'\n+\telse\n+\t\techo\n+\t\techo 'To abort & restore, invoke:'\n+\t\techo \"    $(print_caller --abort)\"\n+\t\techo 'To continue, invoke:'\n+\t\techo \"    $(print_caller --continue)\"\n+\t\ttest \"$WHY\" = 'pause' || {\n+\t\t\techo 'To skip the current instruction, invoke:'\n+\t\t\techo \"    $(print_caller --skip)\"\n+\t\t}\n+\tfi\n+\texit 0\n+}\n+\n+is_standalone () {\n+\ttest $# -eq 2 &&\n+\ttest \"$2\" = '--' &&\n+\ttest -z \"$BATCHMODE\" &&\n+\ttest -z \"$onto\" &&\n+\ttest \"$VERBOSE\" -eq 1\n+}\n+\n+\n+### Option handling and startup\n+\n+onto=\n+BATCHMODE=\n+CALLERSTRING=\n+VERBOSE=1\n+CALLER=\n+CALLER_ABRT=\n+CALLER_CONT=\n+CALLER_SKIP=\n+while test $# -gt 0\n+do\n+\tcase \"$1\" in\n+\t--continue)\n+\t\tis_standalone \"$@\" || usage\n+\t\tassure_caller\n+\t\tdo_continue\n+\t\t;;\n+\t--abort)\n+\t\tis_standalone \"$@\" || usage\n+\t\tassure_caller\n+\t\tdo_abort\n+\t\t;;\n+\t--skip)\n+\t\tis_standalone \"$@\" || usage\n+\t\tassure_caller\n+\t\tdo_skip\n+\t\t;;\n+\t--status)\n+\t\tis_standalone \"$@\" || usage\n+\t\tassure_caller\n+\t\tdo_status\n+\t\t;;\n+\t--edit)\n+\t\tis_standalone \"$@\" || usage\n+\t\tdo_edit\n+\t\t;;\n+\t--caller)\n+\t\t###############################################################\n+\t\t# This feature is for user scripts only. (Hence undocumented.)\n+\t\t# User scripts should pass an argument like:\n+\t\t# --caller=\"git foo|abrt|go|next\"\n+\t\t# on every git sequencer call. (It is only ignored on\n+\t\t# --edit and --status.)\n+\t\t# So git sequencer knows that\n+\t\t# \"git foo abrt\" will abort,\n+\t\t# \"git foo go\" will continue and\n+\t\t# \"git foo next\" will skip the sequencing process.\n+\t\t# This is useful if your user script does some extra\n+\t\t# preparations or cleanup before/after calling\n+\t\t#   git sequencer --caller=\"...\" --abort|--continue|--skip\n+\t\t#\n+\t\t# Running git-sequencer without the same --caller string\n+\t\t# fails then, until the sequencing process has finished or\n+\t\t# aborted.\n+\t\t#\n+\t\t# Btw, --caller=\"my_tiny_script.sh|-a||\" will be\n+\t\t# interpreted, that users must invoke \"my_tiny_script.sh -a\"\n+\t\t# to abort, but can invoke \"git sequencer --continue\" and\n+\t\t# \"git sequencer --skip\" to continue or skip.\n+\t\t# And it is also possible to provide three different scripts\n+\t\t# by --caller=\"|script 1|tool 2|util 3\".\n+\t\t#\n+\t\t# If your user script does not need any special\n+\t\t# abort/continue/skip behavior, then just do NOT pass\n+\t\t# the --caller option.\n+\t\t###############################################################\n+\t\tshift\n+\t\texpr \"x$1\" : 'x.*|.*|.*|.*$' >/dev/null ||\n+\t\t\tdie 'Wrong --caller format.'\n+\t\tCALLERSTRING=\"$1\"\n+\t\t;;\n+\t-B)\n+\t\tBATCHMODE=t\n+\t\t# XXX: we still have abort on editor invokations\n+\t\t;;\n+\t--onto)\n+\t\tshift\n+\t\tONTO=\"$1\"\n+\t\ttest $(git cat-file -t \"$ONTO\") = 'commit' ||\n+\t\t\tdie \"$ONTO is no commit or branch.\"\n+\t\t;;\n+\t-q)\n+\t\tVERBOSE=0\n+\t\t# XXX: If there were no editors,\n+\t\t# we could just do exec >/dev/null\n+\t\t;;\n+\t-v)\n+\t\tVERBOSE=2\n+\t\t# or increment it if we have several verbosity steps\n+\t\t;;\n+\t--)\n+\t\tshift\n+\t\tbreak\n+\t\t;;\n+\t*)\n+\t\tdie \"$1 currently not implemented.\"\n+\t\t;;\n+\tesac\n+\tshift\n+done\n+test $# -gt 1 && usage\n+\n+do_startup \"$1\"\n-- \n1.5.6.361.g18ea7\n"},{"id":"82290","messageId":"1215277204-20926-1-git-send-email-s-beyer@gmx.net","threadId":"14239","inReplyTo":"1214879914-17866-3-git-send-email-s-beyer@gmx.net","subject":"[PATCH v2 2/4] Add git-sequencer prototype documentation","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-05T17:00:04Z","receivedAt":"2008-07-05T17:00:04Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Mentored-by: Christian Couder <chriscool@tuxfamily.org>\nMentored-by: Daniel Barkalow <barkalow@iabervon.org>\nSigned-off-by: Stephan Beyer <s-beyer@gmx.net>\n---\nThis contains some feedback of Jakub.\n\n Documentation/git-sequencer.txt |  387 +++++++++++++++++++++++++++++++++++++++\n 1 files changed, 387 insertions(+), 0 deletions(-)\n create mode 100644 Documentation/git-sequencer.txt\n\ndiff --git a/Documentation/git-sequencer.txt b/Documentation/git-sequencer.txt\nnew file mode 100644\nindex 0000000..1a9eda4\n--- /dev/null\n+++ b/Documentation/git-sequencer.txt\n@@ -0,0 +1,387 @@\n+git-sequencer(1)\n+================\n+\n+NAME\n+----\n+git-sequencer - Execute a sequence of git instructions\n+\n+SYNOPSIS\n+--------\n+[verse]\n+'git-sequencer' [--batch] [--onto=<base>] [--verbose|--quiet] [<file>]\n+'git-sequencer' --continue | --skip | --abort | --edit | --status\n+\n+\n+DESCRIPTION\n+-----------\n+Executes a sequence of git instructions to HEAD or `<base>`.\n+The sequence is given by `<file>` or standard input.\n+Also see 'TODO FILE FORMAT' below.\n+\n+Before doing anything, the TODO file is checked for correct syntax\n+and sanity.\n+\n+In case of a conflict or request in the TODO file, git-sequencer will\n+pause. On conflict you can use git-diff to locate the markers (`<<<<<<<`)\n+and make edits to resolve the conflict.\n+\n+For each file you edit, you need to tell git the changes by doing\n+\n+    git add <file>\n+\n+After resolving the conflict manually and updating the index with the\n+desired resolution, you can continue the sequencing process with\n+\n+    git sequencer --continue\n+\n+Alternatively, you can undo the git-sequencer progress with\n+\n+    git sequencer --abort\n+\n+or skip the current instruction with\n+\n+    git sequencer --skip\n+\n+or correct the TODO file with\n+\n+    git sequencer --edit\n+\n+During pauses or when finished with the sequencing task, the current\n+HEAD will always be the result of the last processed instruction.\n+\n+\n+OPTIONS\n+-------\n+<file>::\n+\tFilename of the TODO file.  If omitted, standard input is used.\n+\tSee 'TODO FILE FORMAT' below.\n+\n+-B::\n+--batch::\n+\tRun in batch mode. If unexpected user intervention is needed\n+\t(e.g. a conflict or the need to run an editor), git-sequencer fails.\n++\n+Note that the sanity check fails, if you use this option\n+and an instruction like `edit` or `pause` is in the TODO file.\n+\n+--onto=<base>::\n+\tCheckout given commit or branch before sequencing.\n+\tIf you provide a branch, sequencer will make the provided\n+\tchanges on the branch, i.e. the branch will be changed.\n+\n+--continue::\n+\tRestart the sequencing process after having resolved a merge conflict.\n+\n+--abort::\n+\tRestore the original branch and abort the sequence operation.\n+\n+--skip::\n+\tRestart the sequencing process by skipping the current instruction.\n+\n+--status::\n+\tShow the current status of git-sequencer and what\n+\toperations can be done to change that status.\n+\n+--edit::\n+\tInvoke editor to edit the unprocessed part of the TODO file.\n++\n+The file is syntax- and sanity-checked afterwards, so that you can\n+safely run `git sequencer --skip` or `--continue` after editing.\n+If you nonetheless noticed that you made a mistake, you can\n+overwrite `.git/sequencer/todo` with `.git/sequencer/todo.old` and\n+rerun `git sequencer --edit`.\n++\n+If the check fails you are prompted if you want to correct your\n+changes, edit again, cancel editing or really want to save.\n+\n+-q::\n+--quiet::\n+\tSuppress output.\n+\t(Not yet implemented.)\n+\n+-v::\n+--verbose::\n+\tBe more verbose.\n+\n+\n+NOTES\n+-----\n+\n+When sequencing, it is possible, that you are changing the history of\n+a branch in a way that can cause problems for anyone who already has\n+a copy of the branch in their repository and tries to pull updates from\n+you.  You should understand the implications of using git-sequencer on\n+a repository that you share.\n+\n+git-sequencer will usually be called by another git porcelain, like\n+linkgit:git-am[1] or linkgit:git-rebase[1].\n+\n+\n+TODO FILE FORMAT\n+----------------\n+\n+The TODO file contains basically one instruction per line.\n+\n+Blank lines will be ignored.\n+All characters after a `#` character will be ignored until the end of a line.\n+\n+The following instructions can be used:\n+\n+\n+edit <commit>::\n+\tPicks a commit and pauses the sequencer process to let you\n+\tmake changes.\n++\n+This is a short form for `pick <commit> and `pause` on separate lines.\n+\n+\n+mark <mark>::\n+\tSet a symbolic mark for the last commit.\n+\t`<mark>` is an unsigned integer starting at 1 and\n+\tprefixed with a colon, e.g. `:1`.\n++\n+The marks can help if you want to refer to commits that you\n+created during the sequencer process, e.g. if you want to\n+merge such a commit.\n++\n+The set marks are removed after the sequencer has completed.\n+\n+\n+merge [options] <commit-ish1> <commit-ish2> ... <commit-ishN>::\n+\tMerge commits into HEAD.\n++\n+You can refer to a commit by a mark.\n++\n+If you do not provide a commit message (using `-F`, `-m`, `-C`, `-M`,\n+or `--standard`), an editor will be invoked.\n++\n+See the following list and 'GENERAL OPTIONS' for values of `options`:\n+\n+\t--standard;;\n+\t\tGenerates a commit message like 'Merge ... into HEAD'.\n+\t\tSee also linkgit:git-fmt-merge-msg[1].\n+\n+\t-s <strategy>;;\n+\t--strategy=<strategy>;;\n+\t\tUse the given merge strategy.\n+\t\tSee also linkgit:git-merge[1].\n+\n+\n+pick [options] <commit>::\n+\tPick (see linkgit:git-cherry-pick[1]) a commit.\n+\tSequencer will pause on conflicts.\n++\n+See the following list and 'GENERAL OPTIONS' for values of `options`:\n+\n+\t-R;;\n+\t--reverse;;\n+\t\tRevert the changes introduced by pick <commit>.\n+\n+\t--mainline=<n>;;\n+\t\tAllows you to pick merge commits by specifying the\n+\t\tparent number (beginning from 1) to let sequencer\n+\t\treplay the changes relative to the specified parent.\n+\t\t+\n+This option does not work together with `-R`.\n+\n+\n+patch [options] <file>::\n+\tIf file `<file>` is a pure (diff) patch, then apply the patch.\n+\tIf no `--message` option is given, an editor will\n+\tbe invoked to enter a commit message.\n++\n+If `<file>` is a linkgit:git-format-patch[1]-formatted patch,\n+then the patch will be commited.\n++\n+See the following list and 'GENERAL OPTIONS' for values of `options`:\n+\n+\t-3;;\n+\t--3way;;\n+\t\tWhen the patch does not apply cleanly, fall back on\n+\t\t3-way merge, if the patch records the identity of blobs\n+\t\tit is supposed to apply to, and we have those blobs\n+\t\tavailable locally.\n+\n+\t-k;;\n+\t\tPass `-k` flag to `git-mailinfo` (see linkgit:git-mailinfo[1]).\n+\n+\t-n;;\n+\t\tPass `-n` flag to `git-mailinfo` (see linkgit:git-mailinfo[1]).\n+\n+\t--exclude=<path-pattern>;;\n+\t\tDo not apply changes to files matching the given path pattern.\n+\t\tThis can be useful when importing patchsets, where you want to\n+\t\texclude certain files or directories.\n+\n+\t-R;;\n+\t--reverse;;\n+\t\tApply the patch in reverse.\n+\n+\t--no-add;;\n+\t\tWhen applying a patch, ignore additions made by the\n+\t\tpatch.  This can be used to extract the common part between\n+\t\ttwo files by first running `diff` on them and applying\n+\t\tthe result with this option, which would apply the\n+\t\tdeletion part but not addition part.\n+\n+\t--whitespace=<action>;;\n+\t\tSpecify behavior on whitespace errors.\n+\t\tSee linkgit:git-apply[1] for a detailed description.\n+\n+\t--context=<n>;;\n+\t\tEnsure at least <n> lines of surrounding context match before\n+\t\tand after each change.  When fewer lines of surrounding\n+\t\tcontext exist they all must match.  By default no context is\n+\t\tever ignored.\n+\n+\t--inaccurate-eof;;\n+\t\tUnder certain circumstances, some versions of diff do not\n+\t\tcorrectly detect a missing new-line at the end of the file.\n+\t\tAs a result, patches created by such diff programs do not\n+\t\trecord incomplete lines correctly.\n+\t\tThis option adds support for applying such patches by\n+\t\tworking around this bug.\n+\n+\t-p<n>;;\n+\t\tRemove <n> leading slashes from traditional diff paths.\n+\t\tThe default is 1.\n+\n+\t--unidiff-zero;;\n+\t\tBy default, linkgit:git-apply[1] expects that the patch being\n+\t\tapplied is a unified diff with at least one line of context.\n+\t\tThis provides good safety measures, but breaks down when\n+\t\tapplying a diff generated with --unified=0. To bypass these\n+\t\tchecks use '--unidiff-zero'.\n+\n+\n+pause::\n+\tPauses the sequencer process to let you manually make changes.\n+\tFor example, you can re-edit the done commit, fix bugs or typos,\n+\tor you can make further commits on top of HEAD before continuing.\n++\n+After you have finished your changes and added them to the index,\n+invoke `git-sequencer --continue`.\n+If you only want to edit the last commit message with an editor,\n+run `git commit --amend` (see linkgit:git-commit[1]) before saying\n+`--continue`.\n+\n+\n+ref <ref>::\n+\tSet ref `<ref>` to the current HEAD, see also\n+\tlinkgit:git-update-ref[1].\n+\n+\n+reset <commit-ish>::\n+\tGo back (see linkgit:git-reset[1] `--hard`) to commit `<commit-ish>`.\n+\t`<commit-ish>` can also be given by a mark, if prefixed with a colon.\n+\n+\n+squash [options] <commit>::\n+\tAdd the changes introduced by `<commit>` to the last commit.\n++\n+See 'GENERAL OPTIONS' for values of `options`.\n+\n+squash [options] --from <mark>::\n+\tSquash all commits from the given mark into one commit.\n+\tThere must not be any `merge` instructions between the\n+\t`mark` instruction and this `squash --from` instruction.\n++\n+See the following list and 'GENERAL OPTIONS' for values of `options`:\n+\n+\t--collect-signoffs;;\n+\t\tCollect the Signed-off-by: lines of each commit and\n+\t\tadd them to the squashed commit message.\n+\t\t(Not yet implemented.)\n+\n+\t--include-merges;;\n+\t\tSanity check does not fail if you have merges\n+\t\tbetween HEAD and <mark>.\n+\n+\n+GENERAL OPTIONS\n+---------------\n+\n+Besides some special options, the instructions\n+`patch`, `merge`, `pick`, `squash` take the following general options:\n+\n+--author=<author>::\n+\tOverride the author name and e-mail address used in the commit.\n+\tUse `A U Thor <author@example.com>` format.\n+\n+-C <commit-ish>::\n+--reuse-commit=<commit-ish>::\n+\tReuse message and authorship data from specified commit.\n+\n+-M <commit-ish>\n+--reuse-message=<commit-ish>::\n+\tReuse message from specified commit.\n+\tNote, that only the commit message is reused\n+\tand not the authorship information.\n+\n+-F <file>::\n+--file=<file>::\n+\tTake the commit message from the given file.\n+\n+-m <msg>::\n+--message=<msg>::\n+\tUse the given `<msg>` as the commit message.\n+\n+--signoff::\n+\tAdd `Signed-off-by:` line to the commit message (if not yet there),\n+\tusing the committer identity of yourself.\n+\n+-e::\n+--edit::\n+\tRegardless what commit message options are given,\n+\tinvoke the editor to allow editing of the commit message.\n+\n+\n+RETURN VALUES\n+-------------\n+\n+git-sequencer returns:\n+\n+* `0`, if git-sequencer successfully completed all the instructions\n+       in the TODO file or successfully aborted after\n+       `git sequencer --abort`,\n+* `2`, on user-requested pausing, e.g.\n+       when using the `edit` instruction.\n+* `3`, on pauses that are not requested, e.g.\n+       when there are conflicts to resolve\n+       or errors in the TODO file.\n+* any other value on error, e.g.\n+  running git-sequencer on a bare repository.\n+\n+\n+EXAMPLES\n+--------\n+\n+TODO [Here the usage of all commands should become clear.]\n+\n+\n+SEE ALSO\n+--------\n+\n+linkgit:git-add[1],\n+linkgit:git-am[1],\n+linkgit:git-cherry-pick[1],\n+linkgit:git-commit[1],\n+linkgit:git-fmt-merge-msg[1],\n+linkgit:git-format-patch[1],\n+linkgit:git-rebase[1],\n+linkgit:git-reset[1],\n+linkgit:git-update-ref[1]\n+\n+\n+Authors\n+-------\n+Written by Stephan Beyer <s-beyer@gmx.net>.\n+\n+\n+Documentation\n+-------------\n+Documentation by Stephan Beyer and the git-list <git@vger.kernel.org>.\n+\n+GIT\n+---\n+Part of the linkgit:git[1] suite\n-- \n1.5.6.361.g18ea7\n"},{"id":"82292","messageId":"20080705173130.GA8099@leksak.fem-net","threadId":"14239","inReplyTo":"1214879914-17866-4-git-send-email-s-beyer@gmx.net","subject":"Re: [RFC/PATCH 3/4] Add git-sequencer test suite (t3350)","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-05T17:31:30Z","receivedAt":"2008-07-05T17:31:30Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nI've just noticed that those tag names:\n  +\tgit tag A &&\n  +\tgit tag B &&\n  +\tgit tag C &&\n  +\tgit tag D &&\n  +\tgit tag E &&\n  +\tgit tag F &&\n  +\tgit tag I &&\n  +ref refs/tags/CE\nare perhaps a bad idea, because they could also be an abbreviated SHA1.\nAs it seems, git does not think this is ambiguous, since the exact tag\nname exists.\nSo it could make sense to add a non-[0-9A-Fa-f] prefix, but it does not\nseem to be necessary.  Hmmm, so this mail is just a mental note :)\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82295","messageId":"7vk5g0ryaw.fsf@gitster.siamese.dyndns.org","threadId":"14239","inReplyTo":"20080705173130.GA8099@leksak.fem-net","subject":"Re: [RFC/PATCH 3/4] Add git-sequencer test suite (t3350)","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-05T18:16:55Z","receivedAt":"2008-07-05T18:16:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stephan Beyer <s-beyer@gmx.net> writes:\n\n> Hi,\n>\n> I've just noticed that those tag names:\n>   +\tgit tag A &&\n>   +\tgit tag B &&\n>   +\tgit tag C &&\n>   +\tgit tag D &&\n>   +\tgit tag E &&\n>   +\tgit tag F &&\n>   +\tgit tag I &&\n>   +ref refs/tags/CE\n> are perhaps a bad idea, because they could also be an abbreviated SHA1.\n\nI do not think we take a single letter abbrev so it should be fine.\n"},{"id":"82318","messageId":"7vzlovq0t6.fsf@gitster.siamese.dyndns.org","threadId":"14239","inReplyTo":"alpine.DEB.1.00.0807041617320.9925@racer","subject":"Re: [PATCH] Allow cherry-picking root commits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-07-06T01:05:41Z","receivedAt":"2008-07-06T01:05:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> There is no good reason why cherry-picking root commits should not be \n> allowed.\n\nHmm, does \"cherry-pick a root commit\" even have a well defined semantics,\nother than \"if there is no overlap in files just add the files in\"?  I\nhave a feeling that it is more likely to be a user error, a sign that the\nuser mistyped the name of the commit to pick.\n"},{"id":"82320","messageId":"alpine.DEB.1.00.0807060331250.3557@eeepc-johanness","threadId":"14239","inReplyTo":"7vzlovq0t6.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Allow cherry-picking root commits","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-07-06T01:37:05Z","receivedAt":"2008-07-06T01:37:05Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 5 Jul 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > There is no good reason why cherry-picking root commits should not be \n> > allowed.\n> \n> Hmm, does \"cherry-pick a root commit\" even have a well defined \n> semantics, other than \"if there is no overlap in files just add the \n> files in\"?\n\nYes.  You can easily add the files identically, or some similar files, in \nwhich case you get an easily-resolved conflict.\n\n> I have a feeling that it is more likely to be a user error, a sign that \n> the user mistyped the name of the commit to pick.\n\nNow, now, that is too harsh a statement!\n\nOften I start my work from a tarball, just because the git import takes so \nlong that I can fiddle with the thing already while the import runs.\n\nAnd guess what, it would be easier to rebase that series onto an imported \ntag for me.  The first commit would not result in changes, since it would \nimport the identical tree.  Or it would barf, in which case I would know \nthat I got the wrong branch point to rebase onto.\n\nAt the moment, I play games that need a deep knowledge of Git, which _I_ \nhave, but not necessarily occasional Git users.\n\nCiao,\nDscho\n"},{"id":"82357","messageId":"20080706113238.GB6731@leksak.fem-net","threadId":"14239","inReplyTo":"alpine.DEB.1.00.0807060331250.3557@eeepc-johanness","subject":"t3503: Add test case for identical files","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-06T11:32:38Z","receivedAt":"2008-07-06T11:32:38Z","isPatch":false,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"---\n\nOn Sun, Jul 06, 2008, Johannes Schindelin wrote:\n> Hi,\n> \n> On Sat, 5 Jul 2008, Junio C Hamano wrote:\n> \n> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> > \n> > > There is no good reason why cherry-picking root commits should not be \n> > > allowed.\n> > \n> > Hmm, does \"cherry-pick a root commit\" even have a well defined \n> > semantics, other than \"if there is no overlap in files just add the \n> > files in\"?\n> \n> Yes.  You can easily add the files identically, or some similar files, in \n> which case you get an easily-resolved conflict.\n\nI think this test case shows that it works for identical files.\nThis patch is btw just to show Junio that it works. ;)\nBecause I'd like to see Dscho's patch in git, too.\n\nRegards.\n\n t/t3503-cherry-pick-root.sh |   21 ++++++++++++++++++++-\n 1 files changed, 20 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t3503-cherry-pick-root.sh b/t/t3503-cherry-pick-root.sh\nindex b0faa29..bcb6610 100755\n--- a/t/t3503-cherry-pick-root.sh\n+++ b/t/t3503-cherry-pick-root.sh\n@@ -6,14 +6,23 @@ test_description='test cherry-picking a root commit'\n \n test_expect_success setup '\n \n+\t: > file0 &&\n \techo first > file1 &&\n+\techo second > file2 &&\n+\tgit add file0 &&\n \tgit add file1 &&\n \ttest_tick &&\n \tgit commit -m \"first\" &&\n \n+\tgit symbolic-ref HEAD refs/heads/sharefile &&\n+\trm .git/index file0 &&\n+\tgit add file1 &&\n+\tgit add file2 &&\n+\ttest_tick &&\n+\tgit commit -m \"file1 and file2\" &&\n+\n \tgit symbolic-ref HEAD refs/heads/second &&\n \trm .git/index file1 &&\n-\techo second > file2 &&\n \tgit add file2 &&\n \ttest_tick &&\n \tgit commit -m \"second\"\n@@ -23,6 +32,16 @@ test_expect_success setup '\n test_expect_success 'cherry-pick a root commit' '\n \n \tgit cherry-pick master &&\n+\ttest -f file0 &&\n+\ttest first = $(cat file1)\n+\n+'\n+\n+test_expect_success 'cherry-pick a root commit with identical files' '\n+\n+\tgit checkout sharefile &&\n+\tgit cherry-pick master &&\n+\ttest -f file0 &&\n \ttest first = $(cat file1)\n \n '\n-- \n1.5.6.361.g18ea7\nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82358","messageId":"20080706113548.GC6731@leksak.fem-net","threadId":"14239","inReplyTo":"alpine.DEB.1.00.0807041617320.9925@racer","subject":"Re: [PATCH] Allow cherry-picking root commits","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-06T11:35:48Z","receivedAt":"2008-07-06T11:35:48Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"On Fri, Jul 04, Johannes Schindelin wrote:\n> +\tif (!commit->parents) {\n> +\t\tif (action == REVERT)\n> +\t\t\tdie (\"Cannot revert a root commit\");\n\nI btw wondered why _reverting_ a root commit should not work.\nThen I tried to quickly add this feature and saw what's the point:\nmerge-recursive wants a remote -- this\n> +\targv[i++] = next_sha1;\nto be set :)\nSo the change is not as trivial as I thought.\nAnd yes, there may even be no use case for reverting root commits.\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82362","messageId":"alpine.LSU.1.00.0807061446160.3486@wbgn129.biozentrum.uni-wuerzburg.de","threadId":"14239","inReplyTo":"20080706113548.GC6731@leksak.fem-net","subject":"Re: [PATCH] Allow cherry-picking root commits","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-07-06T12:48:17Z","receivedAt":"2008-07-06T12:48:17Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 6 Jul 2008, Stephan Beyer wrote:\n\n> And yes, there may even be no use case for reverting root commits.\n\nThat weighs much heavier than that it would be hard to implement.  \nWhen writing the patch, I spent 2 minutes thinking about a possible case \nwhere reverting a root commit would make sense.  And I came up with none.\n\nIt can be sensible to undo _parts_ of it, but then it is no longer about \nreverting the root commit, but about applying a partial patch with a new \ncommit message, and we support that quite nicely already.\n\nCiao,\nDscho\n"},{"id":"82581","messageId":"200807081237.51456.jnareb@gmail.com","threadId":"14239","inReplyTo":"1215277204-20926-1-git-send-email-s-beyer@gmx.net","subject":"Re: [PATCH v2 2/4] Add git-sequencer prototype documentation","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-07-08T10:37:50Z","receivedAt":"2008-07-08T10:37:50Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Sat, 5 July 2008, Stephan Beyer wrote:\n\n> +git-sequencer(1)\n\n> +TODO FILE FORMAT\n\n> +edit <commit>::\n> +mark <mark>::\n> +merge [options] <commit-ish1> <commit-ish2> ... <commit-ishN>::\n> +pick [options] <commit>::\n> +patch [options] <file>::\n> +pause::\n> +ref <ref>::\n> +reset <commit-ish>::\n> +squash [options] <commit>::\n> +squash [options] --from <mark>::\n\nA few comments and ideas:\n\n1. Splitting a patch\n\nI cannot comment well on git-sequencer, as I have started using\nStGIT patch management interface instead of git-rebase in times when\nthere were no \"git rebase --interactive\".  Nevertheless working with\nStGIT is a bit similar to working with interactive rebase...\n\nI don't find myself wanting to join two patches into one (to squadh\na commit) perhaps because when I want to add something to a commit\n(to a patch) I simply go to this patch, edit files, and refresh the\npatch.  From time to time however I find myself SPLITTING a patch,\nfor example extracting something added \"by the way\"/\"while at it\"\ninto separate commit (like late separate better documenting\nproject_index file format from adding optional description field\nto project_index file format).\n\nCurrently I don't see easy way to do this with git-sequencer.\n\n\n2. Patch based rebase\n\ngit-rebase by default, and for speed, uses git-format-patch / git-am\npipeline (utilizing '--rebasing' option to git-am to avoid changing\ncommit messages, even if they do not follow commit message conventions).\nIf you want for plain \"git rebase\" to use git-sequencer, it should be\neasy to support this \"engine\"; therefore perhaps it would be good\nto add some equivalent of \"git format-patch\" to the TODO file format.\n\n\n3. Checking rebase\n\nUsually when you are interacting with upstream by sending patches by\nemail, the last part before sending series of patches is git-rebase\non top of current work.  It would be nice if there were some way to\nhave \"git rebase\" (via git-sequencer) to check that all commits\n(perhaps with some explicitly stated in TODO file exceptions) passes\npre-commit hook (checking for whitespaces and conflict markers), and\nif possibly also either test suite, or relevant parts of test suite.\n\nSo perhaps extending TODO format by \"check <script>\" or\n\"check-all <script>\"?\n\n\nI'm just not sure if it is worth adding to TOD file format...\n-- \nJakub Narebski\nPoland\n"},{"id":"82592","messageId":"20080708114907.GG6726@leksak.fem-net","threadId":"14239","inReplyTo":"200807081237.51456.jnareb@gmail.com","subject":"Re: [PATCH v2 2/4] Add git-sequencer prototype documentation","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-07-08T11:49:07Z","receivedAt":"2008-07-08T11:49:07Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nOn Tue, Jul 08, 2008, Jakub Narebski wrote:\n> 1. Splitting a patch\n[...]\n> Currently I don't see easy way to do this with git-sequencer.\n\nI've needed this, too, and I've added this use case in the EXAMPLES\nsection that will be included in the next patchset.\nBasically it is the same as the rebase documentation says:\nduring a pause (by \"edit\" or \"pause\" insn) reset to HEAD^, add only\nthose parts to the index you want to have in the first patch and commit\nand then repeat this.\n\nWhen I've experienced this need the first time, I thought about how\nsequencer could ease that.\nA first idea was something like \"take only files X, Y, Z from commit ...\"\nor a --exclude as patch has.\nBut often splitting a patch is not done file-wise, but hunk-wise or even\nline-wise.\nSo my second idea was to add an option to \"pause\" that just invokes\nthe \"reset HEAD^\". That makes it easy, I think.\nHow should this option be called?\n\n> 2. Patch based rebase\n> \n> git-rebase by default, and for speed, uses git-format-patch / git-am\n> pipeline (utilizing '--rebasing' option to git-am to avoid changing\n> commit messages, even if they do not follow commit message conventions).\n> If you want for plain \"git rebase\" to use git-sequencer, it should be\n> easy to support this \"engine\"; therefore perhaps it would be good\n> to add some equivalent of \"git format-patch\" to the TODO file format.\n\nImho the patch generation should be done by git-rebase.\n\n> 3. Checking rebase\n> \n> Usually when you are interacting with upstream by sending patches by\n> email, the last part before sending series of patches is git-rebase\n> on top of current work.  It would be nice if there were some way to\n> have \"git rebase\" (via git-sequencer) to check that all commits\n> (perhaps with some explicitly stated in TODO file exceptions) passes\n> pre-commit hook (checking for whitespaces and conflict markers), and\n> if possibly also either test suite, or relevant parts of test suite.\n> \n> So perhaps extending TODO format by \"check <script>\" or\n> \"check-all <script>\"?\n\nThat seems to be useful indeed and reminds me of\n\"git bisect run <script>\".\nPerhaps it's also better to call it \"run\" so that it is a generic\nway of running scripts from sequencer and if they fail, sequencer\nwill pause, if they pass, everything goes on.\n\nWhat about this?\n\n\nrun [--dir=<path>] [--] <cmd> <args>...::\n\tRun command `<cmd>` with arguments `<args>`.\n\tPause (conflict-like) if exit status is non-zero.\n+\nIf `<path>` is set, sequencer will change directory to `<path>`\nbefore running the command and change back after exit.\n\n\n\nRegards,\n  Stephan\n\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"82684","messageId":"20080709052052.GA21390@diana.vm.bytemark.co.uk","threadId":"14239","inReplyTo":"200807081237.51456.jnareb@gmail.com","subject":"Re: [PATCH v2 2/4] Add git-sequencer prototype documentation","fromName":"Karl Hasselström","fromEmail":"kha@treskal.com","sentAt":"2008-07-09T05:20:52Z","receivedAt":"2008-07-09T05:20:52Z","isPatch":true,"sender":{"key":"kha@treskal.com","avatar":"https://gravatar.com/avatar/f0120c734b5279b345075a28521e1ac66acb20c9913ffe9bf6ae97e53f7f3f13?d=mp&s=160"},"body":"(I've hijacked this thread and started talking mostly about StGit\ninstead of git-sequencer; if you're not interested, you can stop\nreading now.)\n\nOn 2008-07-08 12:37:50 +0200, Jakub Narebski wrote:\n\n> 1. Splitting a patch\n>\n> I cannot comment well on git-sequencer, as I have started using\n> StGIT patch management interface instead of git-rebase in times when\n> there were no \"git rebase --interactive\". Nevertheless working with\n> StGIT is a bit similar to working with interactive rebase...\n>\n> I don't find myself wanting to join two patches into one (to squadh\n> a commit) perhaps because when I want to add something to a commit\n> (to a patch) I simply go to this patch, edit files, and refresh the\n> patch.\n\nYou can do this without having to manually go to the right patch with\nthe -p <patchname> flag to stg refresh. In my experimental branch,\nthis even works together with path limited refresh, or refresh of just\nthe index.\n\nMy own workflow is different: I generally make a large number of\nrather small \"work-in-progress\" commits without much of a commit\nmessage, and every now and then (while I still have everything in\nshort-term memory) I use \"stg coalesce\" to make one or more \"real\"\npatches out of them. Because I've committed such small pieces in the\nfirst place, I rarely need to split a patch.\n\n> From time to time however I find myself SPLITTING a patch, for\n> example extracting something added \"by the way\"/\"while at it\" into\n> separate commit (like late separate better documenting project_index\n> file format from adding optional description field to project_index\n> file format).\n\nThe best way I've found of splitting a patch in StGit is to open the\ndiff in an Emacs buffer, then pop the patch, and then use Emacs' cool\ndiff-mode features to apply hunks selectively, split hunks, edit files\nin place, etc., and committing at the points where I want patch\nboundaries. Occasionally, I'll push and pop the patch to get a new\ndiff with only the remaining stuff.\n\nI imagine something like this could work without StGit as well, since\nit's mostly Emacs doing all the hard work. (And I suppose there are\nother tools besides Emacs that can do this?)\n\n-- \nKarl Hasselström, kha@treskal.com\n      www.treskal.com/kalle\n"}]}