On 08.06.12 22:07, konglu@xxxxxxxxxxxxxxx wrote: > > Torsten Bögershausen <tboegi@xxxxxx> a écrit : > >> On 08.06.12 21:15, konglu@xxxxxxxxxxxxxxx wrote: >>> >>> Torsten Bögershausen <tboegi@xxxxxx> a écrit : >> >>> Which part does not apply ? If you skip the part that's implementing the >>> exec option, of course Git will not recognize it. >> >> >> Hej, >> 2 questions: >> a) Where should it apply ? >> I tried to apply it on commit f623ca1cae600e97cb0b38131fdd33e4fb669cf8 > > I just tried to apply it on that commit and it works for me. What's the > error message ? > >> b) Does the line from my log >> "error: unknown option `exec'" >> tell us anything? > > Yes, that the patch was not applied ^^'. ------------------------------------------------ That's the outcome, if I try to re-apply it: Applying: Fwd: [PATCHv3 2/2] rebase [-i --exec | -ix] <CMD>... error: patch failed: Documentation/git-rebase.txt:210 error: Documentation/git-rebase.txt: patch does not apply Patch failed at 0001 Fwd: [PATCHv3 2/2] rebase [-i --exec | -ix] <CMD>... When you have resolved this problem run "git am --resolved". If you would prefer to skip this patch, instead run "git am --skip". To restore the original branch and stop patching run "git am --abort". ===================== And after my fumbling, the diff looks like this (see below). It seems that something changed, because the error line is different- Sorry if I messed something up here, it looks as if the functionality implementing the "exec" is missing in my code base. For me it looks as if I only picked up the test cases, and I'm missing something. In this case it would be helpful if you just re-send the patch to my email, and I can try to re-do the patch based on f623ca1cae600e97cb0b38, or whatever you specify. Does that makes sense? /Torsten ------------------------ git diff f623ca1cae600e97cb0b38..63884a991c9d8 ================================================= diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 147fa1a..1dd95c4 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -8,9 +8,9 @@ git-rebase - Forward-port local commits to the updated upstream head SYNOPSIS -------- [verse] -'git rebase' [-i | --interactive] [options] [--onto <newbase>] +'git rebase' [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>] -'git rebase' [-i | --interactive] [options] --onto <newbase> +'git rebase' [-i | --interactive] [options] [--exec <cmd>] --onto <newbase> --root [<branch>] 'git rebase' --continue | --skip | --abort @@ -210,11 +210,29 @@ rebase.autosquash:: OPTIONS ------- -<newbase>:: - Starting point at which to create the new commits. If the - --onto option is not specified, the starting point is - <upstream>. May be any valid commit, and not just an - existing branch name. +-x <cmd>:: +--exec <cmd>:: + Automatically add "exec" followed by <cmd> between each commit + applications. Using this option along with --autosquash adds + the exec line after the squash/fixeup series only. <cmd> + stands for shell commands. The --exec option has to be + specified. (see INTERACTIVE MODE below) ++ +This has to be used along with the `--interactive` option explicitly. +You may execute several commands between each commit applications. +For this, you can use one instance of exec: + git rebase -i --exec "cmd1; cmd2; ...". +You can also insert several instances of exec, if you wish to +only have one command per line for example: + git rebase -i --exec "cmd1" --exec "cmd2" ... + +--onto <newbase>:: + With this option, git rebase takes all commits from <branch>, + that are not in <upstream>, and transplant them on top of + <newbase>. <newbase> is the starting point at which to create + the new commits. If the --onto option is not specified, the + starting point is <upstream>. May be any valid commit, and + not just an existing branch name. + As a special case, you may use "A\...B" as a shortcut for the merge base of A and B if there is exactly one merge base. You can @@ -521,6 +539,28 @@ in `$SHELL`, or the default shell if `$SHELL` is not set), so you can use shell features (like "cd", ">", ";" ...). The command is run from the root of the working tree. +---------------------------------- +$ git rebase -i --exec "make test" +---------------------------------- + +This command lets you check that intermediate commits are compilable. +The todo list becomes like that: + +-------------------- +pick 5928aea one +exec make test +pick 04d0fda two +exec make test +pick ba46169 three +exec make test +pick f4593f9 four +exec make test +-------------------- + +If the option '-i' is missing, The command will return a message +error. If there is no <cmd> specified behind --exec, the command will +return a message error and the usage page of 'git rebase'. + SPLITTING COMMITS ----------------- diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 0c19b7c..dc9e7e9 100644 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -684,6 +684,22 @@ rearrange_squash () { rm -f "$1.sq" "$1.rearranged" } +# Add commands after a pick or after a squash/fixup serie +# in the todo list. +add_exec_commands () { + OIFS=$IFS + IFS=$LF + for i in $cmd + do + tmp=$(sed "/^pick .*/i\exec $i" "$1") + echo "$tmp" >"$1" + tmp=$(sed '1d' "$1") + echo "$tmp" >"$1" + echo "exec $i" >>"$1" + done + IFS=$OIFS +} + case "$action" in continue) # do we have anything to commit? @@ -857,6 +873,8 @@ fi test -s "$todo" || echo noop >> "$todo" test -n "$autosquash" && rearrange_squash "$todo" +test -n "$cmd" && add_exec_commands "$todo" + cat >> "$todo" << EOF # Rebase $shortrevisions onto $shortonto diff --git a/git-rebase.sh b/git-rebase.sh index e616737..87b21e3 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -3,7 +3,8 @@ # Copyright (c) 2005 Junio C Hamano. # -USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--no-ff] [--onto <newbase>] [<upstream>|--root] [<branch>] [--quiet | -q]' +USAGE='[--interactive | -i] [--exec | -x <cmd>] [-v] [--force-rebase | -f] + [--no-ff] [--onto <newbase>] [<upstream>|--root] [<branch>] [--quiet | -q]' LONG_USAGE='git-rebase replaces <branch> with a new branch of the same name. When the --onto option is provided the new branch starts out with a HEAD equal to <newbase>, otherwise it is equal to <upstream> @@ -30,8 +31,8 @@ Example: git-rebase master~1 topic SUBDIRECTORY_OK=Yes OPTIONS_KEEPDASHDASH= OPTIONS_SPEC="\ -git rebase [-i] [options] [--onto <newbase>] [<upstream>] [<branch>] -git rebase [-i] [options] --onto <newbase> --root [<branch>] +git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>] +git rebase [-i] [options] [--exec <cmd>] --onto <newbase> --root [<branch>] git-rebase [-i] --continue | --abort | --skip -- Available options are @@ -43,6 +44,7 @@ s,strategy=! use the given merge strategy no-ff! cherry-pick all commits, even if unchanged m,merge! use merging strategies to rebase i,interactive! let the user edit the list of commits to rebase +x,exec=! add exec lines after each commit of the editable list k,keep-empty preserve empty commits during rebase f,force-rebase! force rebase even if branch is up to date X,strategy-option=! pass the argument through to the merge strategy @@ -76,6 +78,7 @@ If you would prefer to skip this patch, instead run \"git rebase --skip\". To check out the original branch and stop rebasing run \"git rebase --abort\". " unset onto +cmd= strategy= strategy_opts= do_merge= @@ -220,6 +223,11 @@ do onto="$2" shift ;; + -x) + test 2 -le "$#" || usage + cmd="${cmd:+"$cmd$LF"} $2" + shift + ;; -i) interactive_rebase=explicit ;; @@ -305,6 +313,12 @@ do done test $# -gt 2 && usage +if test -n "$cmd" && + test "$interactive_rebase" != explicit +then + die "--exec option must be used with --interactive option\n" +fi + if test -n "$action" then test -z "$in_progress" && die "No rebase in progress?" diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 025c1c6..4fe98d5 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -755,4 +755,128 @@ test_expect_success 'rebase-i history with funny messages' ' test_cmp expect actual ' + +test_expect_success 'prepare for rebase -i --exec' ' + git checkout master && + git checkout -b execute && + test_commit one_exec main.txt one_exec && + test_commit two_exec main.txt two_exec && + test_commit three_exec main.txt three_exec +' + + +test_expect_success 'running "git rebase -i --exec git show HEAD"' ' + git rebase -i --exec "git show HEAD" HEAD~2 >actual && + ( + FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && + export FAKE_LINES && + git rebase -i HEAD~2 >expected + ) && + sed '1,9d' expected >expect && + mv expect expected && + test_cmp expected actual +' + + +test_expect_success 'running "git rebase --exec git show HEAD -i"' ' + git reset --hard execute && + git rebase --exec "git show HEAD" -i HEAD~2 >actual && + ( + FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && + export FAKE_LINES && + git rebase -i HEAD~2 >expected + ) && + sed '1,9d' expected >expect && + mv expect expected && + test_cmp expected actual +' + + +test_expect_success 'running "git rebase -ix git show HEAD"' ' + git reset --hard execute && + git rebase -ix "git show HEAD" HEAD~2 >actual && + ( + FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && + export FAKE_LINES && + git rebase -i HEAD~2 >expected + ) && + sed '1,9d' expected >expect && + mv expect expected && + test_cmp expected actual +' + + +test_expect_success 'rebase -ix with several <CMD>' ' + git reset --hard execute && + git rebase -ix "git show HEAD; pwd" HEAD~2 >actual && + ( + FAKE_LINES="1 exec_git_show_HEAD;_pwd 2 exec_git_show_HEAD;_pwd" && + export FAKE_LINES && + git rebase -i HEAD~2 >expected + ) && + sed '1,9d' expected >expect && + mv expect expected && + test_cmp expected actual +' + + +test_expect_success 'rebase -ix with several instances of --exec' ' + git reset --hard execute && + git rebase -i --exec "git show HEAD" --exec "pwd" HEAD~2 >actual && + ( + FAKE_LINES="1 exec_git_show_HEAD exec_pwd 2 + exec_git_show_HEAD exec_pwd" && + export FAKE_LINES && + git rebase -i HEAD~2 >expected + ) && + sed '1,11d' expected >expect && + mv expect expected && + test_cmp expected actual +' + + +test_expect_success 'rebase -ix with --autosquash' ' + git reset --hard execute && + git checkout -b autosquash && + echo second >second.txt && + git add second.txt && + git commit -m "fixup! two_exec" && + echo bis >bis.txt && + git add bis.txt && + git commit -m "fixup! two_exec" && + ( + git checkout -b autosquash_actual && + git rebase -i --exec "git show HEAD" --autosquash HEAD~4 >actual + ) && + git checkout autosquash && + ( + git checkout -b autosquash_expected && + FAKE_LINES="1 fixup 3 fixup 4 exec_git_show_HEAD 2 exec_git_show_HEAD" && + export FAKE_LINES && + git rebase -i HEAD~4 >expected + ) && + sed '1,13d' expected >expect && + mv expect expected && + test_cmp expected actual +' + + +test_expect_success 'rebase --exec without -i shows error message' ' + git reset --hard execute && + test_must_fail git rebase --exec "git show HEAD" HEAD~2 2>actual && + echo "--exec option must be used with --interactive option\n" >expected && + test_cmp expected actual +' + + +test_expect_success 'rebase -i --exec without <CMD> shows error message and usage' ' + git reset --hard execute && + test_must_fail git rebase -i --exec 2>actual && + sed '1d' actual >tmp && + mv tmp actual && + test_must_fail git rebase -h >expected && + test_cmp expected actual && + git checkout master +' + test_done -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html