{"thread":{"id":"24691","subject":"Black smoke from git rebase -i exec","startedAt":"2010-08-10T13:08:02Z","lastAt":"2011-01-26T07:33:14Z","messageCount":38,"participants":["Ævar Arnfjörð Bjarmason","Matthieu Moy","Johannes Sixt","Junio C Hamano","Jonathan Nieder","Nicolas Sebrecht","Thomas Rast","Johannes Schindelin","Joshua Jensen","Jay Soffian"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"147633","messageId":"AANLkTikCgSNRipTbjiL+uPOqCL3WXwn08_QV=UJ7EwvT@mail.gmail.com","threadId":"24691","inReplyTo":null,"subject":"Black smoke from git rebase -i exec","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-08-10T13:08:02Z","receivedAt":"2010-08-10T13:08:02Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"There's some black smoke in pu after the git rebase -i series was\napplied: http://smoke.git.nix.is/app/projects/report_details/14\n\nNote: just the t3404-rebase-interactive.sh failure, not\nt6040-tracking-info.sh, that's something else.\n\nHere's the --verbose output from the test, hopefully that helps, if\nnot I can supply some additional info:\n\n    Initialized empty Git repository in\n/tmp/build-and-install-git-olpK/t/trash\ndirectory.t3404-rebase-interactive/.git/\n    expecting success:\n    \ttest_commit A file1 &&\n    \ttest_commit B file1 &&\n    \ttest_commit C file2 &&\n    \ttest_commit D file1 &&\n    \ttest_commit E file3 &&\n    \tgit checkout -b branch1 A &&\n    \ttest_commit F file4 &&\n    \ttest_commit G file1 &&\n    \ttest_commit H file5 &&\n    \tgit checkout -b branch2 F &&\n    \ttest_commit I file6\n    \tgit checkout -b conflict-branch A &&\n    \tfor n in one two three four\n    \tdo\n    \t\ttest_commit $n conflict\n    \tdone &&\n    \tgit checkout -b no-conflict-branch A &&\n    \tfor n in J K L M\n    \tdo\n    \t\ttest_commit $n file$n\n    \tdone &&\n    \tgit checkout -b no-ff-branch A &&\n    \tfor n in N O P\n    \tdo\n    \t\ttest_commit $n file$n\n    \tdone\n\n    [master (root-commit) 6e62bf8] A\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 file1\n    [master 313fe96] B\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 1 deletions(-)\n    [master d0f65f2] C\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 file2\n    [master 0547e3f] D\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 1 deletions(-)\n    [master 8f99a4f] E\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 file3\n    Switched to a new branch 'branch1'\n    [branch1 cfefd94] F\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 file4\n    [branch1 83751a6] G\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 1 deletions(-)\n    [branch1 4373208] H\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 file5\n    Switched to a new branch 'branch2'\n    [branch2 615be62] I\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 file6\n    Switched to a new branch 'conflict-branch'\n    [conflict-branch b895952] one\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 conflict\n    [conflict-branch 766a798] two\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 1 deletions(-)\n    [conflict-branch 1eadf03] three\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 1 deletions(-)\n    [conflict-branch f91a2b3] four\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 1 deletions(-)\n    Switched to a new branch 'no-conflict-branch'\n    [no-conflict-branch 808874f] J\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 fileJ\n    [no-conflict-branch 265b89e] K\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 fileK\n    [no-conflict-branch 6b0f5e6] L\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 fileL\n    [no-conflict-branch 3389558] M\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 fileM\n    Switched to a new branch 'no-ff-branch'\n    [no-ff-branch 53b4423] N\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 fileN\n    [no-ff-branch cc47714] O\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 fileO\n    [no-ff-branch faef1a5] P\n     Author: A U Thor <author@example.com>\n     1 files changed, 1 insertions(+), 0 deletions(-)\n     create mode 100644 fileP\n    ok 1 - setup\n\n    expecting success:\n    \tgit checkout master &&\n    \tFAKE_LINES=\"1 exec_touch_touch-one 2 exec_touch_touch-two\nexec_false exec_touch_touch-three 3 4\n    \t\texec_touch_\\\"touch-file__name_with_spaces\\\";_touch_touch-after-semicolon\n5\" \\\n    \t\ttest_must_fail git rebase -i A &&\n    \ttest -f touch-one &&\n    \ttest -f touch-two &&\n    \t! test -f touch-three &&\n    \ttest $(git rev-parse C) = $(git rev-parse HEAD) || {\n    \t\techo \"Stopped at wrong revision:\"\n    \t\techo \"($(git describe --tags HEAD) instead of C)\"\n    \t\tfalse\n    \t} &&\n    \tgit rebase --continue &&\n    \ttest -f touch-three &&\n    \ttest -f \"touch-file  name with spaces\" &&\n    \ttest -f touch-after-semicolon &&\n    \ttest $(git rev-parse master) = $(git rev-parse HEAD) || {\n    \t\techo \"Stopped at wrong revision:\"\n    \t\techo \"($(git describe --tags HEAD) instead of master)\"\n    \t\tfalse\n    \t} &&\n    \trm -f touch-*\n\n    Switched to a new branch 'master'\n    Rebasing (4/4)\nSuccessfully rebased and updated refs/heads/master.\n    Stopped at wrong revision:\n    (E instead of C)\n    Stopped at wrong revision:\n    (E instead of master)\n    not ok - 2 rebase -i with the exec command\n    #\t\n    #\t\tgit checkout master &&\n    #\t\tFAKE_LINES=\"1 exec_touch_touch-one 2 exec_touch_touch-two\nexec_false exec_touch_touch-three 3 4\n    #\t\t\texec_touch_\\\"touch-file__name_with_spaces\\\";_touch_touch-after-semicolon\n5\" \\\n    #\t\t\ttest_must_fail git rebase -i A &&\n    #\t\ttest -f touch-one &&\n    #\t\ttest -f touch-two &&\n    #\t\t! test -f touch-three &&\n    #\t\ttest $(git rev-parse C) = $(git rev-parse HEAD) || {\n    #\t\t\techo \"Stopped at wrong revision:\"\n    #\t\t\techo \"($(git describe --tags HEAD) instead of C)\"\n    #\t\t\tfalse\n    #\t\t} &&\n    #\t\tgit rebase --continue &&\n    #\t\ttest -f touch-three &&\n    #\t\ttest -f \"touch-file  name with spaces\" &&\n    #\t\ttest -f touch-after-semicolon &&\n    #\t\ttest $(git rev-parse master) = $(git rev-parse HEAD) || {\n    #\t\t\techo \"Stopped at wrong revision:\"\n    #\t\t\techo \"($(git describe --tags HEAD) instead of master)\"\n    #\t\t\tfalse\n    #\t\t} &&\n    #\t\trm -f touch-*\n    #\t\n\n    expecting success:\n    \tgit checkout master &&\n    \tmkdir subdir && cd subdir &&\n    \tFAKE_LINES=\"1 exec_touch_touch-subdir\" \\\n    \t\tgit rebase -i HEAD^ &&\n    \tcd .. &&\n    \ttest -f touch-subdir &&\n    \trm -fr subdir\n\n    Already on 'master'\n    rebase -i script before editing:\n    pick 8f99a4f E\n\n    rebase -i script after editing:\n    pick 8f99a4f E\n    exec touch touch-subdir\n    Rebasing (2/2)\nExecuting: touch touch-subdir\n    Successfully rebased and updated refs/heads/master.\n    ok 3 - rebase -i with the exec command runs from tree root\n\n    expecting success:\n    \tgit checkout master &&\n    \tFAKE_LINES=\"exec_echo_foo_>file1 1\" \\\n    \t\ttest_must_fail git rebase -i HEAD^ &&\n    \ttest $(git rev-parse master^) = $(git rev-parse HEAD) || {\n    \t\techo \"Stopped at wrong revision:\"\n    \t\techo \"($(git describe --tags HEAD) instead of master^)\"\n    \t\tfalse\n    \t} &&\n    \tgit reset --hard &&\n    \tgit rebase --continue\n\n    Already on 'master'\n    Rebasing (1/1)\nSuccessfully rebased and updated refs/heads/master.\n    Stopped at wrong revision:\n    (E instead of master^)\n    not ok - 4 rebase -i with the exec command checks tree cleanness\n    #\t\n    #\t\tgit checkout master &&\n    #\t\tFAKE_LINES=\"exec_echo_foo_>file1 1\" \\\n    #\t\t\ttest_must_fail git rebase -i HEAD^ &&\n    #\t\ttest $(git rev-parse master^) = $(git rev-parse HEAD) || {\n    #\t\t\techo \"Stopped at wrong revision:\"\n    #\t\t\techo \"($(git describe --tags HEAD) instead of master^)\"\n    #\t\t\tfalse\n    #\t\t} &&\n    #\t\tgit reset --hard &&\n    #\t\tgit rebase --continue\n    #\t\n\n    # failed 2 among 4 test(s)\n    1..4\n\n(I modified the test to only run the failing tests)\n"},{"id":"147636","messageId":"vpqlj8ezizq.fsf@bauges.imag.fr","threadId":"24691","inReplyTo":"AANLkTikCgSNRipTbjiL+uPOqCL3WXwn08_QV=UJ7EwvT@mail.gmail.com","subject":"Re: Black smoke from git rebase -i exec","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-10T13:37:29Z","receivedAt":"2010-08-10T13:37:29Z","isPatch":false,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n\n> There's some black smoke in pu after the git rebase -i series was\n> applied: http://smoke.git.nix.is/app/projects/report_details/14\n\nStrange, I can't reproduce this on my box (tried on RHEL x86_64 and\nDebian i686).\n\n>     expecting success:\n...\n>     \trm -f touch-*\n>\n>     Switched to a new branch 'master'\n\nAt this point, I get \n\nrebase -i script before editing:\npick 313fe96 B\npick d0f65f2 C\npick 0547e3f D\npick 8f99a4f E\n\nrebase -i script after editing:\npick 313fe96 B\nexec touch touch-one\npick d0f65f2 C\nexec touch touch-two\nexec false\nexec touch touch-three\npick 0547e3f D\npick 8f99a4f E\nexec touch \"touch-file  name with spaces\"; touch touch-after-semicolon\n\nwhich you don't seem to get on your side. I get the same as you if I\ncomment out the \"set_fake_editor\" line at the top of the script. So, I\nsuspect there's something very wrong that prevents it from doing its\njob.\n\nCan you add some debug\n\necho \"$EDITOR\"\necho \"$FAKE_EDITOR\"\n\nsomewhere in the test to see what happens?\n\n>     Rebasing (4/4)\n> Successfully rebased and updated refs/heads/master.\n>     Stopped at wrong revision:\n>     (E instead of C)\n>     Stopped at wrong revision:\n>     (E instead of master)\n\n(here, it's definitely doing as if the todolist had not been edited)\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"147638","messageId":"AANLkTimgRu=nRFpO+QW758SWbQ+Vs+8gtpAc4N-cNWr6@mail.gmail.com","threadId":"24691","inReplyTo":"vpqlj8ezizq.fsf@bauges.imag.fr","subject":"Re: Black smoke from git rebase -i exec","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-08-10T13:57:05Z","receivedAt":"2010-08-10T13:57:05Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Tue, Aug 10, 2010 at 13:37, Matthieu Moy\n<Matthieu.Moy@grenoble-inp.fr> wrote:\n> Ęvar Arnfjörš Bjarmason <avarab@gmail.com> writes:\n>\n>> There's some black smoke in pu after the git rebase -i series was\n>> applied: http://smoke.git.nix.is/app/projects/report_details/14\n>\n> Strange, I can't reproduce this on my box (tried on RHEL x86_64 and\n> Debian i686).\n\nHi. The issue appears to be that there's some non-POSIX code in your\npatch (but I didn't check what). The test works for me with bash, but\nfails with dash (which is the Debian testing /bin/sh).\n\nCan you try with dash or some other non-bash POSIX shell and see if it\nfails?\n"},{"id":"147639","messageId":"4C615E5E.3090301@viscovery.net","threadId":"24691","inReplyTo":"AANLkTimgRu=nRFpO+QW758SWbQ+Vs+8gtpAc4N-cNWr6@mail.gmail.com","subject":"Re: Black smoke from git rebase -i exec","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2010-08-10T14:12:46Z","receivedAt":"2010-08-10T14:12:46Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 8/10/2010 15:57, schrieb Ævar Arnfjörð Bjarmason:\n> On Tue, Aug 10, 2010 at 13:37, Matthieu Moy\n> <Matthieu.Moy@grenoble-inp.fr> wrote:\n>> Ęvar Arnfjörš Bjarmason <avarab@gmail.com> writes:\n>>\n>>> There's some black smoke in pu after the git rebase -i series was\n>>> applied: http://smoke.git.nix.is/app/projects/report_details/14\n>>\n>> Strange, I can't reproduce this on my box (tried on RHEL x86_64 and\n>> Debian i686).\n> \n> Hi. The issue appears to be that there's some non-POSIX code in your\n> patch (but I didn't check what). The test works for me with bash, but\n> fails with dash (which is the Debian testing /bin/sh).\n> \n> Can you try with dash or some other non-bash POSIX shell and see if it\n> fails?\n\nThe culprit is commands like these:\n\n\tFAKE_LINES=\"exec_echo_foo_>file1 1\" \\\n\t\ttest_must_fail git rebase -i HEAD^ &&\n\nYou cannot apply single-command-export if the command is a shell function.\nYou must rewrite this as:\n\n\t(\n\t\texport FAKE_LINES=\"...\" &&\n\t\ttest_must_fail git rebase ....\n\t) &&\n\n-- Hannes\n"},{"id":"147641","messageId":"AANLkTikVB6VoSy3=XVHqGsA7xH39MgDwh2hDnX89enfM@mail.gmail.com","threadId":"24691","inReplyTo":"4C615E5E.3090301@viscovery.net","subject":"Re: Black smoke from git rebase -i exec","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-08-10T14:16:38Z","receivedAt":"2010-08-10T14:16:38Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Tue, Aug 10, 2010 at 14:12, Johannes Sixt <j.sixt@viscovery.net> wrote:\n> You cannot apply single-command-export if the command is a shell function.\n> You must rewrite this as:\n>\n>        (\n>                export FAKE_LINES=\"...\" &&\n>                test_must_fail git rebase ....\n>        ) &&\n\nExcept that's not portable either, it should be:\n\n    FAKE_LINES=\"...\" &&\n    export FAKE_LINES &&\n\ttest_must_fail git rebase ...\n\nSee the other examples in t3404-rebase-interactive.sh\n"},{"id":"147646","messageId":"vpq62ziv788.fsf@bauges.imag.fr","threadId":"24691","inReplyTo":"AANLkTikVB6VoSy3=XVHqGsA7xH39MgDwh2hDnX89enfM@mail.gmail.com","subject":"Re: Black smoke from git rebase -i exec","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-10T15:05:11Z","receivedAt":"2010-08-10T15:05:11Z","isPatch":false,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n\n> On Tue, Aug 10, 2010 at 14:12, Johannes Sixt <j.sixt@viscovery.net> wrote:\n>> You cannot apply single-command-export if the command is a shell function.\n>> You must rewrite this as:\n>>\n>>        (\n>>                export FAKE_LINES=\"...\" &&\n>>                test_must_fail git rebase ....\n>>        ) &&\n>\n> Except that's not portable either, it should be:\n>\n>     FAKE_LINES=\"...\" &&\n>     export FAKE_LINES &&\n> \ttest_must_fail git rebase ...\n>\n> See the other examples in t3404-rebase-interactive.sh\n\nYes, I had found this. New patch comming soon.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"147649","messageId":"1281453472-29835-1-git-send-email-Matthieu.Moy@imag.fr","threadId":"24691","inReplyTo":"vpq62ziv788.fsf@bauges.imag.fr","subject":"[PATCH 1/2 (fix broken test)] rebase -i: add exec command to launch a shell command","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-10T15:17:51Z","receivedAt":"2010-08-10T15:17:51Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"The typical usage pattern would be to run a test (or simply a compilation\ncommand) at given points in history.\n\nThe shell command is ran (from the worktree root), and the rebase is\nstopped when the command fails, to give the user an opportunity to fix\nthe problem before continuing with \"git rebase --continue\".\n\nThis needs a little rework of skip_unnecessary_picks, which wasn't robust\nenough to deal with lines like\n\n  exec >\"file    name with many spaces\"\n\nin the todolist. The new version extracts command, sha1 and rest from\neach line, but outputs the line itself verbatim to avoid changing the\nwhitespace layout.\n\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\nThis fixes the non-POSIX behavior of the tests found by Ævar Arnfjörð\nBjarmason (FAKE_LINES=foo test_must_fail ... does not work).\n\nAlso, I replaced \"touch foo\" with \">foo\" and found a small bug. This\nis the skip_unnecessary_picks of the commit message and of the patch\nbelow.\n\n Documentation/git-rebase.txt  |   24 ++++++++++++++++\n git-rebase--interactive.sh    |   38 +++++++++++++++++++++++--\n t/lib-rebase.sh               |    2 +\n t/t3404-rebase-interactive.sh |   61 +++++++++++++++++++++++++++++++++++++++++\n 4 files changed, 122 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex be23ad2..9c68b66 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -459,6 +459,30 @@ sure that the current HEAD is \"B\", and call\n $ git rebase -i -p --onto Q O\n -----------------------------\n \n+Reordering and editing commits usually creates untested intermediate\n+steps.  You may want to check that your history editing did not break\n+anything by running a test, or at least recompiling at intermediate\n+points in history by using the \"exec\" command (shortcut \"x\").  You may\n+do so by creating a todo list like this one:\n+\n+-------------------------------------------\n+pick deadbee Implement feature XXX\n+fixup f1a5c00 Fix to feature XXX\n+exec make\n+pick c0ffeee The oneline of the next commit\n+edit deadbab The oneline of the commit after\n+exec cd subdir; make test\n+...\n+-------------------------------------------\n+\n+The interactive rebase will stop when a command fails (i.e. exits with\n+non-0 status) to give you an opportunity to fix the problem. You can\n+continue with `git rebase --continue`.\n+\n+The \"exec\" command launches the command in a shell (the one specified\n+in `$SHELL`, or the default shell if `$SHELL` is not set), so you can\n+use shell features (like \"cd\", \">\", \";\" ...). The command is run from\n+the root of the working tree.\n \n SPLITTING COMMITS\n -----------------\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex b94c2a0..bf49b5b 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -537,6 +537,34 @@ do_next () {\n \t\tesac\n \t\trecord_in_rewritten $sha1\n \t\t;;\n+\tx|\"exec\")\n+\t\tread -r command rest < \"$TODO\"\n+\t\tmark_action_done\n+\t\tprintf 'Executing: %s\\n' \"$rest\"\n+\t\t# \"exec\" command doesn't take a sha1 in the todo-list.\n+\t\t# => can't just use $sha1 here.\n+\t\tgit rev-parse --verify HEAD > \"$DOTEST\"/stopped-sha\n+\t\t${SHELL:-@SHELL_PATH@} -c \"$rest\" # Actual execution\n+\t\tstatus=$?\n+\t\tif test \"$status\" -ne 0\n+\t\tthen\n+\t\t\twarn \"Execution failed: $rest\"\n+\t\t\twarn \"You can fix the problem, and then run\"\n+\t\t\twarn\n+\t\t\twarn \"\tgit rebase --continue\"\n+\t\t\twarn\n+\t\t\texit \"$status\"\n+\t\tfi\n+\t\t# Run in subshell because require_clean_work_tree can die.\n+\t\tif ! (require_clean_work_tree)\n+\t\tthen\n+\t\t\twarn \"Commit or stash your changes, and then run\"\n+\t\t\twarn\n+\t\t\twarn \"\tgit rebase --continue\"\n+\t\t\twarn\n+\t\t\texit 1\n+\t\tfi\n+\t\t;;\n \t*)\n \t\twarn \"Unknown command: $command $sha1 $rest\"\n \t\tif git rev-parse --verify -q \"$sha1\" >/dev/null\n@@ -591,10 +619,13 @@ do_rest () {\n # skip picking commits whose parents are unchanged\n skip_unnecessary_picks () {\n \tfd=3\n-\twhile read -r command sha1 rest\n+\twhile read -r line\n \tdo\n+\t\tcommand=$(echo \"$line\" | sed 's/  */ /' | cut -d ' ' -f 1)\n+\t\tsha1=$(echo \"$line\"    | sed 's/  */ /' | cut -d ' ' -f 2)\n+\t\trest=$(echo \"$line\"    | sed 's/  */ /' | cut -d ' ' -f 3-)\n \t\t# fd=3 means we skip the command\n-\t\tcase \"$fd,$command,$(git rev-parse --verify --quiet $sha1^)\" in\n+\t\tcase \"$fd,$command,$(git rev-parse --verify --quiet \"$sha1\"^)\" in\n \t\t3,pick,\"$ONTO\"*|3,p,\"$ONTO\"*)\n \t\t\t# pick a commit whose parent is current $ONTO -> skip\n \t\t\tONTO=$sha1\n@@ -606,7 +637,7 @@ skip_unnecessary_picks () {\n \t\t\tfd=1\n \t\t\t;;\n \t\tesac\n-\t\tprintf '%s\\n' \"$command${sha1:+ }$sha1${rest:+ }$rest\" >&$fd\n+\t\techo \"$line\" >&$fd\n \tdone <\"$TODO\" >\"$TODO.new\" 3>>\"$DONE\" &&\n \tmv -f \"$TODO\".new \"$TODO\" &&\n \tcase \"$(peek_next_command)\" in\n@@ -957,6 +988,7 @@ first and then run 'git rebase --continue' again.\"\n #  e, edit = use commit, but stop for amending\n #  s, squash = use commit, but meld into previous commit\n #  f, fixup = like \"squash\", but discard this commit's log message\n+#  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\n #\n # If you remove a line here THAT COMMIT WILL BE LOST.\n # However, if you remove everything, the rebase will be aborted.\ndiff --git a/t/lib-rebase.sh b/t/lib-rebase.sh\nindex 6aefe27..6ccf797 100644\n--- a/t/lib-rebase.sh\n+++ b/t/lib-rebase.sh\n@@ -47,6 +47,8 @@ for line in $FAKE_LINES; do\n \tcase $line in\n \tsquash|fixup|edit|reword)\n \t\taction=\"$line\";;\n+\texec*)\n+\t\techo \"$line\" | sed 's/_/ /g' >> \"$1\";;\n \t\"#\")\n \t\techo '# comment' >> \"$1\";;\n \t\">\")\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 9f03ce6..93b181e 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -64,6 +64,67 @@ test_expect_success 'setup' '\n \tdone\n '\n \n+# \"exec\" commands are ran with the user shell by default, but this may\n+# be non-POSIX. For example, if SHELL=zsh then \">file\" doesn't work\n+# to create a file. Unseting SHELL avoids such non-portable behavior\n+# in tests.\n+SHELL=\n+\n+test_expect_success 'rebase -i with the exec command' '\n+\tgit checkout master &&\n+\t(\n+\tFAKE_LINES=\"1 exec_>touch-one\n+\t\t2 exec_>touch-two exec_false exec_>touch-three\n+\t\t3 4 exec_>\\\"touch-file__name_with_spaces\\\";_>touch-after-semicolon 5\" &&\n+\texport FAKE_LINES &&\n+\ttest_must_fail git rebase -i A\n+\t) &&\n+\ttest -f touch-one &&\n+\ttest -f touch-two &&\n+\t! test -f touch-three &&\n+\ttest $(git rev-parse C) = $(git rev-parse HEAD) || {\n+\t\techo \"Stopped at wrong revision:\"\n+\t\techo \"($(git describe --tags HEAD) instead of C)\"\n+\t\tfalse\n+\t} &&\n+\tgit rebase --continue &&\n+\ttest -f touch-three &&\n+\ttest -f \"touch-file  name with spaces\" &&\n+\ttest -f touch-after-semicolon &&\n+\ttest $(git rev-parse master) = $(git rev-parse HEAD) || {\n+\t\techo \"Stopped at wrong revision:\"\n+\t\techo \"($(git describe --tags HEAD) instead of master)\"\n+\t\tfalse\n+\t} &&\n+\trm -f touch-*\n+'\n+\n+test_expect_success 'rebase -i with the exec command runs from tree root' '\n+\tgit checkout master &&\n+\tmkdir subdir && cd subdir &&\n+\tFAKE_LINES=\"1 exec_>touch-subdir\" \\\n+\t\tgit rebase -i HEAD^ &&\n+\tcd .. &&\n+\ttest -f touch-subdir &&\n+\trm -fr subdir\n+'\n+\n+test_expect_success 'rebase -i with the exec command checks tree cleanness' '\n+\tgit checkout master &&\n+\t(\n+\tFAKE_LINES=\"exec_echo_foo_>file1 1\" &&\n+\texport FAKE_LINES &&\n+\ttest_must_fail git rebase -i HEAD^\n+\t) &&\n+\ttest $(git rev-parse master^) = $(git rev-parse HEAD) || {\n+\t\techo \"Stopped at wrong revision:\"\n+\t\techo \"($(git describe --tags HEAD) instead of master^)\"\n+\t\tfalse\n+\t} &&\n+\tgit reset --hard &&\n+\tgit rebase --continue\n+'\n+\n test_expect_success 'no changes are a nop' '\n \tgit checkout branch2 &&\n \tgit rebase -i F &&\n-- \n1.7.2.1.52.g95e25.dirty\n"},{"id":"147648","messageId":"1281453472-29835-2-git-send-email-Matthieu.Moy@imag.fr","threadId":"24691","inReplyTo":"vpq62ziv788.fsf@bauges.imag.fr","subject":"[PATCH 2/2] test-lib: user-friendly alternatives to test [-d|-f|-e]","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-10T15:17:52Z","receivedAt":"2010-08-10T15:17:52Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"The helper functions are implemented, documented, and used in a few\nplaces to validate them, but not everywhere to avoid useless code churn.\n\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\nJust resending this one since I modified PATCH 1/2 and had to resolve\na minor conflict.\n\n t/README                      |    7 +++++++\n t/t3404-rebase-interactive.sh |   18 +++++++++---------\n t/t3407-rebase-abort.sh       |    6 +++---\n t/test-lib.sh                 |   32 ++++++++++++++++++++++++++++++++\n 4 files changed, 51 insertions(+), 12 deletions(-)\n\ndiff --git a/t/README b/t/README\nindex 0d1183c..410499a 100644\n--- a/t/README\n+++ b/t/README\n@@ -467,6 +467,13 @@ library for your script to use.\n    <expected> file.  This behaves like \"cmp\" but produces more\n    helpful output when the test is run with \"-v\" option.\n \n+ - test_path_is_file <file> [<diagnosis>]\n+   test_path_is_dir <dir> [<diagnosis>]\n+   test_path_is_missing <path> [<diagnosis>]\n+\n+   Check whether a file/directory exists or doesn't. <diagnosis> will\n+   be displayed if the test fails.\n+\n  - test_when_finished <script>\n \n    Prepend <script> to a list of commands to run to clean up\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 93b181e..fa02eb3 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -79,18 +79,18 @@ test_expect_success 'rebase -i with the exec command' '\n \texport FAKE_LINES &&\n \ttest_must_fail git rebase -i A\n \t) &&\n-\ttest -f touch-one &&\n-\ttest -f touch-two &&\n-\t! test -f touch-three &&\n+\ttest_path_is_file touch-one &&\n+\ttest_path_is_file touch-two &&\n+\ttest_path_is_missing touch-three \" (should have stopped before)\" &&\n \ttest $(git rev-parse C) = $(git rev-parse HEAD) || {\n \t\techo \"Stopped at wrong revision:\"\n \t\techo \"($(git describe --tags HEAD) instead of C)\"\n \t\tfalse\n \t} &&\n \tgit rebase --continue &&\n-\ttest -f touch-three &&\n-\ttest -f \"touch-file  name with spaces\" &&\n-\ttest -f touch-after-semicolon &&\n+\ttest_path_is_file touch-three &&\n+\ttest_path_is_file \"touch-file  name with spaces\" &&\n+\ttest_path_is_file touch-after-semicolon &&\n \ttest $(git rev-parse master) = $(git rev-parse HEAD) || {\n \t\techo \"Stopped at wrong revision:\"\n \t\techo \"($(git describe --tags HEAD) instead of master)\"\n@@ -105,7 +105,7 @@ test_expect_success 'rebase -i with the exec command runs from tree root' '\n \tFAKE_LINES=\"1 exec_>touch-subdir\" \\\n \t\tgit rebase -i HEAD^ &&\n \tcd .. &&\n-\ttest -f touch-subdir &&\n+\ttest_path_is_file touch-subdir &&\n \trm -fr subdir\n '\n \n@@ -204,7 +204,7 @@ 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/rebase-merge\n+\ttest_path_is_missing .git/rebase-merge\n '\n \n test_expect_success 'abort with error when new base cannot be checked out' '\n@@ -213,7 +213,7 @@ test_expect_success 'abort with error when new base cannot be checked out' '\n \ttest_must_fail git rebase -i master > output 2>&1 &&\n \tgrep \"Untracked working tree file .file1. would be overwritten\" \\\n \t\toutput &&\n-\t! test -d .git/rebase-merge &&\n+\ttest_path_is_missing .git/rebase-merge &&\n \tgit reset --hard HEAD^\n '\n \ndiff --git a/t/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh\nindex 2999e78..fbb3f2e 100755\n--- a/t/t3407-rebase-abort.sh\n+++ b/t/t3407-rebase-abort.sh\n@@ -38,7 +38,7 @@ testrebase() {\n \t\t# Clean up the state from the previous one\n \t\tgit reset --hard pre-rebase &&\n \t\ttest_must_fail git rebase$type master &&\n-\t\ttest -d \"$dotest\" &&\n+\t\ttest_path_is_dir \"$dotest\" &&\n \t\tgit rebase --abort &&\n \t\ttest $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&\n \t\ttest ! -d \"$dotest\"\n@@ -49,7 +49,7 @@ testrebase() {\n \t\t# Clean up the state from the previous one\n \t\tgit reset --hard pre-rebase &&\n \t\ttest_must_fail git rebase$type master &&\n-\t\ttest -d \"$dotest\" &&\n+\t\ttest_path_is_dir \"$dotest\" &&\n \t\ttest_must_fail git rebase --skip &&\n \t\ttest $(git rev-parse HEAD) = $(git rev-parse master) &&\n \t\tgit rebase --abort &&\n@@ -62,7 +62,7 @@ testrebase() {\n \t\t# Clean up the state from the previous one\n \t\tgit reset --hard pre-rebase &&\n \t\ttest_must_fail git rebase$type master &&\n-\t\ttest -d \"$dotest\" &&\n+\t\ttest_path_is_dir \"$dotest\" &&\n \t\techo c > a &&\n \t\techo d >> a &&\n \t\tgit add a &&\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex e8f21d5..d584194 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -541,6 +541,38 @@ test_external_without_stderr () {\n \tfi\n }\n \n+# debugging-friendly alternatives to \"test [-f|-d|-e]\"\n+# The commands test the existence or non-existence of $1. $2 can be\n+# given to provide a more precise diagnosis.\n+test_path_is_file () {\n+\tif ! [ -f \"$1\" ]\n+\tthen\n+\t\techo \"File $1 doesn't exist. $*\"\n+\t\tfalse\n+\tfi\n+}\n+\n+test_path_is_dir () {\n+\tif ! [ -d \"$1\" ]\n+\tthen\n+\t\techo \"Directory $1 doesn't exist. $*\"\n+\t\tfalse\n+\tfi\n+}\n+\n+test_path_is_missing () {\n+\tif [ -e \"$1\" ]\n+\tthen\n+\t\techo \"Path exists:\"\n+\t\tls -ld \"$1\"\n+\t\tif [ $# -ge 1 ]; then\n+\t\t\techo \"$*\"\n+\t\tfi\n+\t\tfalse\n+\tfi\n+}\n+\n+\n # This is not among top-level (test_expect_success | test_expect_failure)\n # but is a prefix that can be used in the test script, like:\n #\n-- \n1.7.2.1.52.g95e25.dirty\n"},{"id":"147802","messageId":"7v62zhyp9e.fsf@alter.siamese.dyndns.org","threadId":"24691","inReplyTo":"1281453472-29835-1-git-send-email-Matthieu.Moy@imag.fr","subject":"Re: [PATCH 1/2 (fix broken test)] rebase -i: add exec command to launch a shell command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-11T18:31:57Z","receivedAt":"2010-08-11T18:31:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matthieu Moy <Matthieu.Moy@imag.fr> writes:\n\n> The typical usage pattern would be to run a test (or simply a compilation\n> command) at given points in history.\n>\n> The shell command is ran (from the worktree root), and the rebase is\n> stopped when the command fails, to give the user an opportunity to fix\n> the problem before continuing with \"git rebase --continue\".\n>\n> This needs a little rework of skip_unnecessary_picks, which wasn't robust\n> enough to deal with lines like\n>\n>   exec >\"file    name with many spaces\"\n>\n> in the todolist. The new version extracts command, sha1 and rest from\n> each line, but outputs the line itself verbatim to avoid changing the\n> whitespace layout.\n\nThanks.\n\n> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\n> index 9f03ce6..93b181e 100755\n> --- a/t/t3404-rebase-interactive.sh\n> +++ b/t/t3404-rebase-interactive.sh\n> @@ -64,6 +64,67 @@ test_expect_success 'setup' '\n>  \tdone\n>  '\n>  \n> +# \"exec\" commands are ran with the user shell by default, but this may\n> +# be non-POSIX. For example, if SHELL=zsh then \">file\" doesn't work\n> +# to create a file. Unseting SHELL avoids such non-portable behavior\n> +# in tests.\n> +SHELL=\n\nTricky but true.\n\nDo we have other callouts that we use $SHELL from the environment?\nexecv_shell_cmd() just runs \"sh -c\" from $PATH so diff (when running\nexternal diff) nor ll-merge (when running external merge driver) that call\nit via run_command_v_opt(RUN_USING_SHELL) are immune to this issue.\n"},{"id":"147879","messageId":"vpq4of0l1b6.fsf@bauges.imag.fr","threadId":"24691","inReplyTo":"7v62zhyp9e.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 1/2 (fix broken test)] rebase -i: add exec command to launch a shell command","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-12T07:47:41Z","receivedAt":"2010-08-12T07:47:41Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Matthieu Moy <Matthieu.Moy@imag.fr> writes:\n>\n>> +# \"exec\" commands are ran with the user shell by default, but this may\n>> +# be non-POSIX. For example, if SHELL=zsh then \">file\" doesn't work\n>> +# to create a file. Unseting SHELL avoids such non-portable behavior\n>> +# in tests.\n>> +SHELL=\n>\n> Tricky but true.\n>\n> Do we have other callouts that we use $SHELL from the environment?\n\nNot as far as I know. \"git grep SHELL\" show mostly \"SHELL_PATH\", and\nthe testsuite passes for me with SHELL=zsh.\n\nThis exec command is a bit of a special case: I wanted the user to\nkeep the advanced features of his shell (for example, the ** wildcard\nof zsh and recent bash), not just allow executing commands.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"159533","messageId":"20110116015941.GA28137@burratino","threadId":"24691","inReplyTo":"1281453472-29835-1-git-send-email-Matthieu.Moy@imag.fr","subject":"[PATCH 0/2] rebase -i: in-editor documentation nits","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-01-16T01:59:41Z","receivedAt":"2011-01-16T01:59:41Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Matthieu Moy wrote:\n\n> +++ b/git-rebase--interactive.sh\n> @@ -957,6 +988,7 @@ first and then run 'git rebase --continue' again.\"\n>  #  e, edit = use commit, but stop for amending\n>  #  s, squash = use commit, but meld into previous commit\n>  #  f, fixup = like \"squash\", but discard this commit's log message\n> +#  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\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\nNit: the \"exec\" command is formatted differently from the commands\naround it, making it stand out (which I don't think is intended).\n\nWhile we're there, patch 2 adds some brief documentation for the\n\"noop\" command.\n\nRoughly based on [1] (which might be a nice patch to revive, by the\nway).  Sane?\n\nJonathan Nieder (2):\n  rebase -i: reword in-editor documentation of \"exec\"\n  rebase -i: explain how to discard all commits\n\n git-rebase--interactive.sh |    3 ++-\n 1 files changed, 2 insertions(+), 1 deletions(-)\n\n[1] http://thread.gmane.org/gmane.comp.version-control.git/161120/focus=162079\n"},{"id":"159534","messageId":"20110116020132.GB28137@burratino","threadId":"24691","inReplyTo":"20110116015941.GA28137@burratino","subject":"[PATCH 1/2] rebase -i: reword in-editor documentation of \"exec\"","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-01-16T02:01:32Z","receivedAt":"2011-01-16T02:01:32Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"The argument to the \"exec\" insn represents a command to be passed to\nthe user's shell.  (At first I misread the description as meaning it\nshould itself be the name of a shell.)\n\nWhile fixing that, format the description to more closely parallel\nthe descriptions of other commands.\n\nBefore:\n\n #  e, edit = use commit, but stop for amending\n #  s, squash = use commit, but meld into previous commit\n #  f, fixup = like \"squash\", but [...]\n #  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\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\nAfter:\n\n [...]\n #  f, fixup = like \"squash\", but [...]\n #  x, exec = run command using shell, and stop if it fails\n #\n # If you remove a line [...]\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\nIt would be nice to say \"stop for amending if it fails\" (or similar)\nto make the relationship to the edit insn clearer, but it is not clear\nhow to make room for that.\n\n git-rebase--interactive.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex a5ffd9a..09aeecf 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -1021,7 +1021,7 @@ first and then run 'git rebase --continue' again.\"\n #  e, edit = use commit, but stop for amending\n #  s, squash = use commit, but meld into previous commit\n #  f, fixup = like \"squash\", but discard this commit's log message\n-#  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\n+#  x, exec = run command using shell, and stop if it fails\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-- \n1.7.4.rc2\n"},{"id":"159535","messageId":"20110116020207.GC28137@burratino","threadId":"24691","inReplyTo":"20110116015941.GA28137@burratino","subject":"[PATCH 2/2] rebase -i: explain how to discard all commits","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-01-16T02:02:07Z","receivedAt":"2011-01-16T02:02:07Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Preparing a patch series for submission (as explained under\nINTERACTIVE MODE in the git rebase manual) sometimes involves\ndiscarding commits representing changes that turned out to be a bad\nidea.  Usually this is quite simple to do by deleting the appropriate\n\"pick\" lines, but if all commits are removed then the \"remove\neverything means abort\" logic kicks in and the rebase is cancelled.\nOne can override that behavior by adding a line with the text \"noop\".\n\nThis is a follow-up to v1.6.0.3~21 (rebase -i: do not fail when there\nis no commit to cherry-pick, 2008-10-10).\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n git-rebase--interactive.sh |    1 +\n 1 files changed, 1 insertions(+), 0 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 09aeecf..d9dfc75 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -1025,6 +1025,7 @@ first and then run 'git rebase --continue' again.\"\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+# Use the \"noop\" command if you really want to remove all commits.\n #\n EOF\n \n-- \n1.7.4.rc2\n"},{"id":"159543","messageId":"vpq39otrvmk.fsf@bauges.imag.fr","threadId":"24691","inReplyTo":"20110116020132.GB28137@burratino","subject":"Re: [PATCH 1/2] rebase -i: reword in-editor documentation of \"exec\"","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2011-01-16T10:27:47Z","receivedAt":"2011-01-16T10:27:47Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> -#  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\n> +#  x, exec = run command using shell, and stop if it fails\n\nI don't think this is a good change to remove the <cmd> part. All\nother commands are used with\n\n<command> <sha1> <subject line>\n\nand I don't think the user would be able to guess that exec is\ndifferent without a hint.\n\nIf the problem is the wording of the sentence that may imply that\n<cmd> should be the shell itself, then why not\n\nx <cmd>, exec <cmd> = run command <cmd> using shell, and stop if it fails\n\n?\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"159581","messageId":"7vwrm2l0ai.fsf@alter.siamese.dyndns.org","threadId":"24691","inReplyTo":"vpq39otrvmk.fsf@bauges.imag.fr","subject":"Re: [PATCH 1/2] rebase -i: reword in-editor documentation of \"exec\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-01-18T15:05:41Z","receivedAt":"2011-01-18T15:05:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:\n\n> Jonathan Nieder <jrnieder@gmail.com> writes:\n>\n>> -#  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\n>> +#  x, exec = run command using shell, and stop if it fails\n>\n> I don't think this is a good change to remove the <cmd> part. All\n> other commands are used with\n>\n> <command> <sha1> <subject line>\n>\n> and I don't think the user would be able to guess that exec is\n> different without a hint.\n\nI tend to agree with you here.\n"},{"id":"159702","messageId":"20110120193923.GA14184@vidovic","threadId":"24691","inReplyTo":"20110116020207.GC28137@burratino","subject":"[PATCH 2/2] Re: rebase -i: explain how to discard all commits","fromName":"Nicolas Sebrecht","fromEmail":"nicolas.s.dev@gmx.fr","sentAt":"2011-01-20T19:39:23Z","receivedAt":"2011-01-20T19:39:23Z","isPatch":true,"sender":{"key":"nicolas.s.dev@gmx.fr","avatar":null},"body":"The 15/01/11, Jonathan Nieder wrote:\n> Preparing a patch series for submission (as explained under\n> INTERACTIVE MODE in the git rebase manual) sometimes involves\n> discarding commits representing changes that turned out to be a bad\n> idea.  Usually this is quite simple to do by deleting the appropriate\n> \"pick\" lines, but if all commits are removed then the \"remove\n> everything means abort\" logic kicks in and the rebase is cancelled.\n> One can override that behavior by adding a line with the text \"noop\".\n> \n> This is a follow-up to v1.6.0.3~21 (rebase -i: do not fail when there\n> is no commit to cherry-pick, 2008-10-10).\n> \n> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>\n> ---\n>  git-rebase--interactive.sh |    1 +\n>  1 files changed, 1 insertions(+), 0 deletions(-)\n> \n> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\n> index 09aeecf..d9dfc75 100755\n> --- a/git-rebase--interactive.sh\n> +++ b/git-rebase--interactive.sh\n> @@ -1025,6 +1025,7 @@ first and then run 'git rebase --continue' again.\"\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> +# Use the \"noop\" command if you really want to remove all commits.\n>  #\n>  EOF\n\nSorry, I think it is confusing. With this help we could understand that\nthe \"noop\" will either\n\n  (a) discard the interactive rebase\n\nor\n\n  (b) _really remove commits_ from that branch\n\nI'm not sure to know how it will act myself. If (a), we could use\nsomething like\n\n  \"However, if you remove everything or use the \"noop\" command, the rebase will be aborted.\"\n\nbut if we are in case (b), I guess it is not necessary and we should\npoint to the 'git reset' command.\n\n-- \nNicolas Sebrecht\n"},{"id":"159704","messageId":"20110120195726.GA11702@burratino","threadId":"24691","inReplyTo":"20110120193923.GA14184@vidovic","subject":"Re: [PATCH 2/2] Re: rebase -i: explain how to discard all commits","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-01-20T19:57:26Z","receivedAt":"2011-01-20T19:57:26Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Nicolas Sebrecht wrote:\n> The 15/01/11, Jonathan Nieder wrote:\n\n>> This is a follow-up to v1.6.0.3~21 (rebase -i: do not fail when there\n>> is no commit to cherry-pick, 2008-10-10).\n[...]\n>>  # However, if you remove everything, the rebase will be aborted.\n>> +# Use the \"noop\" command if you really want to remove all commits.\n[...]\n> Sorry, I think it is confusing. With this help we could understand that\n> the \"noop\" will either\n>\n>   (a) discard the interactive rebase\n>\n> or\n>\n>   (b) _really remove commits_ from that branch\n>\n> I'm not sure to know how it will act myself. If (a), we could use\n> something like\n>\n>   \"However, if you remove everything or use the \"noop\" command, the rebase will be aborted.\"\n>\n> but if we are in case (b), I guess it is not necessary and we should\n> point to the 'git reset' command.\n\nOkay.  I agree that my particular wording was confusing.  Are you\nsaying the \"noop\" command in general is confusing?\n\nThe \"noop\" is itself a non-operation; if you combine \"noop\" with other\ninstructions then the noop itself will have no effect.  Meanwhile if\nyou have _no_ instructions then the rebase is cancelled, while if you\nhave a single \"noop\" instruction, that means \"I have discarded all the\ncommits, but please rebase anyway\".\n\nJonathan\n"},{"id":"159705","messageId":"20110120200827.GB14184@vidovic","threadId":"24691","inReplyTo":"20110120195726.GA11702@burratino","subject":"[PATCH 2/2] Re: rebase -i: explain how to discard all commits","fromName":"Nicolas Sebrecht","fromEmail":"nicolas.s.dev@gmx.fr","sentAt":"2011-01-20T20:08:27Z","receivedAt":"2011-01-20T20:08:27Z","isPatch":true,"sender":{"key":"nicolas.s.dev@gmx.fr","avatar":null},"body":"The 20/01/11, Jonathan Nieder wrote:\n\n> Okay.  I agree that my particular wording was confusing.  Are you\n> saying the \"noop\" command in general is confusing?\n> \n> The \"noop\" is itself a non-operation; if you combine \"noop\" with other\n> instructions then the noop itself will have no effect.  Meanwhile if\n> you have _no_ instructions then the rebase is cancelled, while if you\n> have a single \"noop\" instruction, that means \"I have discarded all the\n> commits, but please rebase anyway\".\n\nOk, I think I get it now. What about adding\n\n  Use \"noop\" with no other instruction to fallback to a non-interactive\n  rebase. If other instructions are present, \"noop\" has no effect.\n\n?\n\n-- \nNicolas Sebrecht\n"},{"id":"159707","messageId":"20110120200949.GB11702@burratino","threadId":"24691","inReplyTo":"vpq39otrvmk.fsf@bauges.imag.fr","subject":"Re: [PATCH 1/2] rebase -i: reword in-editor documentation of \"exec\"","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-01-20T20:09:49Z","receivedAt":"2011-01-20T20:09:49Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Matthieu Moy wrote:\n> Jonathan Nieder <jrnieder@gmail.com> writes:\n\n>> -#  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\n>> +#  x, exec = run command using shell, and stop if it fails\n>\n> I don't think this is a good change to remove the <cmd> part. All\n> other commands are used with\n>\n> <command> <sha1> <subject line>\n>\n> and I don't think the user would be able to guess that exec is\n> different without a hint.\n> \n> If the problem is the wording of the sentence that may imply that\n> <cmd> should be the shell itself, then why not\n\nYes, sorry, I combined two problems into a single patch.  That was a\nmistake.  The current cheat sheet says:\n\n# Rebase 3f14246..a1d7e01 onto 3f14246\n#\n# Commands:\n#  p, pick = use commit\n#  r, reword = use commit, but edit the commit message\n#  e, edit = use commit, but stop for amending\n#  s, squash = use commit, but meld into previous commit\n#  f, fixup = like \"squash\", but discard this commit's log message\n#  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\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\nThis does not make it clear that the format of each line is\n\n\t<instruction> <commit id> <explanatory text that will be printed>\n\nbut the reader will probably infer that from the automatically\ngenerated pick examples above.\n\nWhat about the \"exec\" instruction?  By analogy, I might imagine that\nthe format of that line is\n\n\texec <command> <explanatory text that will be printed>\n\nSo the \"<cmd>\" does not address that question for me.  It does succeed\nin clarifying that \"a shell command\" does not mean an arbitrary shell\ncommand but a user-specified one.\n\nMeanwhile, it makes the cheat sheet harder to visually scan as a table\n\n i, instruction = action performed by instruction\n\nMaybe \"exec\" should be explained outside this table?  For example,\nmaybe something along the lines of\n\n\t x, exec = run an arbitrary command (see below)\n\n\tA line of the form \"exec <command>\" will run <command> using your\n\tshell and stop for investigation or amending if the command fails.\n\n\tIf you remove a line here, THAT COMMIT WILL BE LOST.\n\tHowever, if you remove everything, the rebase will be aborted.\n"},{"id":"159710","messageId":"201101202134.41911.trast@student.ethz.ch","threadId":"24691","inReplyTo":"20110120200827.GB14184@vidovic","subject":"Re: [PATCH 2/2] Re: rebase -i: explain how to discard all commits","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2011-01-20T20:34:41Z","receivedAt":"2011-01-20T20:34:41Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Nicolas Sebrecht wrote:\n> The 20/01/11, Jonathan Nieder wrote:\n> \n> > if you\n> > have a single \"noop\" instruction, that means \"I have discarded all the\n> > commits, but please rebase anyway\".\n> \n> Ok, I think I get it now. What about adding\n> \n>   Use \"noop\" with no other instruction to fallback to a non-interactive\n>   rebase. If other instructions are present, \"noop\" has no effect.\n> \n> ?\n\nNo, that's quite wrong.\n\nThe TODO list is the list of all commits that need to be rebased.  It\ndoes not contain commits that (according to patch-id) are already\ncontained in the upstream (i.e., the base you are rebasing on).  If\nthe list is empty after filtering out such commits, rebase puts 'noop'\nas the only command since \"empty TODO\" is already taken to mean\n\"abort\"\n\nIf you then accept this 'noop' rebase, this effectively makes the\nrebased branch the same as the base branch, sort of like resetting.\n\n(I for one have never accepted such a rebase; if the TODO only\nconsists of noop, that means I made a mistake.)\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"159713","messageId":"7vy66fqoji.fsf@alter.siamese.dyndns.org","threadId":"24691","inReplyTo":"20110120200949.GB11702@burratino","subject":"Re: [PATCH 1/2] rebase -i: reword in-editor documentation of \"exec\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-01-20T20:59:45Z","receivedAt":"2011-01-20T20:59:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> Maybe \"exec\" should be explained outside this table?  For example,\n> maybe something along the lines of\n>\n> \t x, exec = run an arbitrary command (see below)\n\nOk, none of the other insns in the insn sheet mention what the argument to\nthe command means anyway (e.g. \"p, pick = replay the commit\" doesn't say\nexplicitly where the commit comes from), so I think the original patch is\nprobably fine.\n\nIf we wanted to be more helpful, perhaps s/(see below)/specified on the\nrest of the line/ should be sufficient without adding extra lines.\n"},{"id":"159717","messageId":"7vfwsnqn8c.fsf@alter.siamese.dyndns.org","threadId":"24691","inReplyTo":"201101202134.41911.trast@student.ethz.ch","subject":"Re: [PATCH 2/2] Re: rebase -i: explain how to discard all commits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-01-20T21:28:03Z","receivedAt":"2011-01-20T21:28:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n> (I for one have never accepted such a rebase; if the TODO only\n> consists of noop, that means I made a mistake.)\n\nWouldn't that suggest us that if we were to do anything to this message it\nwould be a good idea to teach the user to \"reset --hard\" the branch if no\ncommits truly needs to be replayed on top of the onto-commit?\n"},{"id":"159730","messageId":"20110121003624.GB23139@burratino","threadId":"24691","inReplyTo":"7vy66fqoji.fsf@alter.siamese.dyndns.org","subject":"[PATCH 1/2 v2] rebase -i: clarify in-editor documentation of \"exec\"","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-01-21T00:36:24Z","receivedAt":"2011-01-21T00:36:24Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"The hints in the current \"instruction sheet\" template look like so:\n\n # Rebase 3f14246..a1d7e01 onto 3f14246\n #\n # Commands:\n #  p, pick = use commit\n #  r, reword = use commit, but edit the commit message\n #  e, edit = use commit, but stop for amending\n #  s, squash = use commit, but meld into previous commit\n #  f, fixup = like \"squash\", but discard this commit's log message\n #  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\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\nThis does not make it clear that the format of each line is\n\n\t<insn> <commit id> <explanatory text that will be printed>\n\nbut the reader will probably infer that from the automatically\ngenerated pick examples above it.\n\nWhat about the \"exec\" instruction?  By analogy, I might imagine that\nthe format of that line is \"exec <command> <explanatory text>\", and\nthe \"x <cmd>\" hint does not address that question (at first I read it\nas taking an argument <cmd> that is the name of a shell).  Meanwhile,\nthe mention of <cmd> makes the hints harder to scan as a table.\n\nSo remove the <cmd> and add some words to remind the reader that\n\"exec\" runs a command named by the rest of the line.  To make room, it\nis left to the manpage to explain that that command is run using\n$SHELL and that nonzero status from that command will pause the\nrebase.\n\nWording from Junio.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\nJunio C Hamano wrote:\n\n> If we wanted to be more helpful, perhaps s/(see below)/specified on the\n> rest of the line/ should be sufficient without adding extra lines.\n\nSounds good.\n\n git-rebase--interactive.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex a5ffd9a..a18c9b1 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -1021,7 +1021,7 @@ first and then run 'git rebase --continue' again.\"\n #  e, edit = use commit, but stop for amending\n #  s, squash = use commit, but meld into previous commit\n #  f, fixup = like \"squash\", but discard this commit's log message\n-#  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\n+#  x, exec = run command specified on the rest of the line\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-- \n1.7.4.rc2\n"},{"id":"159732","messageId":"vpqr5c6zqrh.fsf@bauges.imag.fr","threadId":"24691","inReplyTo":"20110121003624.GB23139@burratino","subject":"Re: [PATCH 1/2 v2] rebase -i: clarify in-editor documentation of \"exec\"","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2011-01-21T06:59:14Z","receivedAt":"2011-01-21T06:59:14Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> -#  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\n> +#  x, exec = run command specified on the rest of the line\n\nI don't think dropping \"shell\" is a good idea. In this context,\n\"command\" could mean \"one of pick/fixup/squash/...\", a Git command,\nand at last, an arbitrary line of shell.\n\nI agree that my \"shell command\" wording was confusing too, but maybe\njust adding \"using the shell\" at the end of line would do it.\nOtherwise, I prefered the \"see below + 2 lines explanation\" proposal\nabove.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"159733","messageId":"alpine.DEB.1.00.1101210801210.15247@pacific.mpi-cbg.de","threadId":"24691","inReplyTo":"7vfwsnqn8c.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 2/2] Re: rebase -i: explain how to discard all commits","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2011-01-21T07:04:07Z","receivedAt":"2011-01-21T07:04:07Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 20 Jan 2011, Junio C Hamano wrote:\n\n> Thomas Rast <trast@student.ethz.ch> writes:\n> \n> > (I for one have never accepted such a rebase; if the TODO only \n> > consists of noop, that means I made a mistake.)\n> \n> Wouldn't that suggest us that if we were to do anything to this message \n> it would be a good idea to teach the user to \"reset --hard\" the branch \n> if no commits truly needs to be replayed on top of the onto-commit?\n\nThe important difference between rebase -i && noop on the one, and reset \n--hard on the other hand is that the latter is completely unsafe. I mean, \nutterly completely super-unsafe. And I say that because _this here \ndeveloper_ who is not exactly a Git noob lost stuff that way.\n\nrebase -i checks that all is well and we could come back to the current \nstatus later if we realized that things went horribly wrong.\n\nreset --hard does not do that. No safety net. No reflog. Nada.\n\nHth,\nDscho\n"},{"id":"159735","messageId":"20110121073730.GA26276@burratino","threadId":"24691","inReplyTo":"alpine.DEB.1.00.1101210801210.15247@pacific.mpi-cbg.de","subject":"[PATCH] Documentation: suggest \"reset --keep\" to undo a commit","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-01-21T07:37:30Z","receivedAt":"2011-01-21T07:37:30Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"When one's only goal is to move from one commit to another, reset\n--keep is simply better than reset --hard, since it preserves local\nchanges in the index and worktree when easy and errors out without\ndoing anything when not.  Update the two \"how to remove commits\"\nexamples in this vein.  \"reset --hard\" is still explained in a later\nexample about cleaning up during a merge.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\nJohannes Schindelin wrote:\n\n> rebase -i checks that all is well and we could come back to the current \n> status later if we realized that things went horribly wrong.\n>\n> reset --hard does not do that. No safety net. No reflog. Nada.\n\nRight.  I think we should encourage people to use \"reset --keep\" more\noften.  (In general.  The particular \"rebase to pull\" example just\nmentioned is less obvious.)\n\n Documentation/git-reset.txt |    4 ++--\n 1 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt\nindex fd72976..1f13a1e 100644\n--- a/Documentation/git-reset.txt\n+++ b/Documentation/git-reset.txt\n@@ -148,7 +148,7 @@ Undo a commit, making it a topic branch::\n +\n ------------\n $ git branch topic/wip     <1>\n-$ git reset --hard HEAD~3  <2>\n+$ git reset --keep HEAD~3  <2>\n $ git checkout topic/wip   <3>\n ------------\n +\n@@ -163,7 +163,7 @@ Undo commits permanently::\n +\n ------------\n $ git commit ...\n-$ git reset --hard HEAD~3   <1>\n+$ git reset --keep HEAD~3   <1>\n ------------\n +\n <1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad\n-- \n1.7.4.rc2\n"},{"id":"159736","messageId":"20110121074700.GA26600@burratino","threadId":"24691","inReplyTo":"vpqr5c6zqrh.fsf@bauges.imag.fr","subject":"Re: [PATCH 1/2 v2] rebase -i: clarify in-editor documentation of \"exec\"","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-01-21T07:47:00Z","receivedAt":"2011-01-21T07:47:00Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Matthieu Moy wrote:\n> Jonathan Nieder <jrnieder@gmail.com> writes:\n\n>> -#  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails\n>> +#  x, exec = run command specified on the rest of the line\n>\n> I don't think dropping \"shell\" is a good idea. In this context,\n> \"command\" could mean \"one of pick/fixup/squash/...\", a Git command,\n> and at last, an arbitrary line of shell.\n\nHmm.  I suppose\n\n# Commands:\n#  p, pick = use commit\n#  r, reword = use commit, but edit the commit message\n#  e, edit = use commit, but stop for amending\n#  s, squash = use commit, but meld into previous commit\n#  f, fixup = like \"squash\", but discard this commit's log message\n#  x, exec = run command (the rest of the line) using shell\n\nwould do?\n\nSorry to take so long to get this right.\n"},{"id":"159741","messageId":"vpqpqrqwn8j.fsf@bauges.imag.fr","threadId":"24691","inReplyTo":"20110121074700.GA26600@burratino","subject":"Re: [PATCH 1/2 v2] rebase -i: clarify in-editor documentation of \"exec\"","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2011-01-21T10:43:40Z","receivedAt":"2011-01-21T10:43:40Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> # Commands:\n> #  p, pick = use commit\n> #  r, reword = use commit, but edit the commit message\n> #  e, edit = use commit, but stop for amending\n> #  s, squash = use commit, but meld into previous commit\n> #  f, fixup = like \"squash\", but discard this commit's log message\n> #  x, exec = run command (the rest of the line) using shell\n\nI'm fine with that.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"159758","messageId":"7vsjwmp5cs.fsf@alter.siamese.dyndns.org","threadId":"24691","inReplyTo":"alpine.DEB.1.00.1101210801210.15247@pacific.mpi-cbg.de","subject":"Re: [PATCH 2/2] Re: rebase -i: explain how to discard all commits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-01-21T16:51:47Z","receivedAt":"2011-01-21T16:51:47Z","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>> Wouldn't that suggest us that if we were to do anything to this message \n>> it would be a good idea to teach the user to \"reset --hard\" the branch \n>> if no commits truly needs to be replayed on top of the onto-commit?\n>\n> The important difference between rebase -i && noop on the one, and reset \n> --hard on the other hand is that the latter is completely unsafe. I mean, \n> utterly completely super-unsafe. And I say that because _this here \n> developer_ who is not exactly a Git noob lost stuff that way.\n\nI think \"rebase\" already checks that the index and the working tree is\nclean before starting, so referring to \"reset --hard\" when \"rebase -i\"\nnotices there is absolutely nothing to do is _not_ unsafe, no?\n"},{"id":"159760","messageId":"vpqmxmu2nm3.fsf@bauges.imag.fr","threadId":"24691","inReplyTo":"7vsjwmp5cs.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 2/2] Re: rebase -i: explain how to discard all commits","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2011-01-21T17:05:56Z","receivedAt":"2011-01-21T17:05:56Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n>\n>>> Wouldn't that suggest us that if we were to do anything to this message \n>>> it would be a good idea to teach the user to \"reset --hard\" the branch \n>>> if no commits truly needs to be replayed on top of the onto-commit?\n>>\n>> The important difference between rebase -i && noop on the one, and reset \n>> --hard on the other hand is that the latter is completely unsafe. I mean, \n>> utterly completely super-unsafe. And I say that because _this here \n>> developer_ who is not exactly a Git noob lost stuff that way.\n>\n> I think \"rebase\" already checks that the index and the working tree is\n> clean before starting, so referring to \"reset --hard\" when \"rebase -i\"\n> notices there is absolutely nothing to do is _not_ unsafe, no?\n\nThe point is not about letting rebase do a \"reset --hard\", but to tell\nthe user s/he should have ran \"reset --hard\" instead of rebase. The\ndanger is to teach the user's fingers to type \"reset --hard\" too\noften, which is unsafe ;-).\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"159761","messageId":"7voc7ap3dp.fsf@alter.siamese.dyndns.org","threadId":"24691","inReplyTo":"20110121073730.GA26276@burratino","subject":"Re: [PATCH] Documentation: suggest \"reset --keep\" to undo a commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-01-21T17:34:26Z","receivedAt":"2011-01-21T17:34:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> When one's only goal is to move from one commit to another, reset\n> --keep is simply better than reset --hard, since it preserves local\n> changes in the index and worktree when easy and errors out without\n> doing anything when not.  Update the two \"how to remove commits\"\n> examples in this vein.  \"reset --hard\" is still explained in a later\n> example about cleaning up during a merge.\n\nI agree with the first sentence but I do not think its conclusion would\nlead to changes to \"how to _remove_ commits\".  The examples were written\nin contexts (explanatory text <$n>) where hard makes sense, and the\ncontext needs tweaking to make keep makes more sense than hard does.\n\nFor example, the first one's original sequence is this:\n\n    $ git branch topic/wip\n    $ git reset --hard HEAD~3\n    $ git checkout topic/wip\n\nThe text explains the motivation behind these series of commands in <1>\nbut it has one untold assumption behind it; the user did the review to\nreach the conclusion that the recent changes are premature after fully\ncommitting (i.e. the working tree is clean).  That is why \"hard\" worked\njust fine.\n\nBut the user could do the reviewing and thinking with some local changes\nstill in the working tree (they are incredients for the fourth commit yet\nto be made) and decide to branch at that point.  The description in <1>\nneeds to be updated to hint that there can be uncommitted changes, e.g.\n\n\tYou have worked for some time, made a few commits, and may have\n\tuncommitted changes.  After reviewing the current state, you\n\trealized that ...\n\nUsing --keep may help the user do so, but only if the local changes do not\nconflict with the changes in the recent commits to be discarded, right?\n\n    Side note: Regardless of any of the above, the section header needs to\n    be updated---it is not \"Undo *A* commit\", we are excluding three from\n    the current branch.\n\nBy the way, a more natural way to do this would actually be:\n\n    $ git checkout -b topic/wip\n    $ git branch -f @{-1} HEAD~3\n\nor using the stash:\n\n    $ git stash ;# save local changes\n    $ git branch topic/wip ;# and mark the tip before rewinding\n    $ git reset --hard HEAD~3 ;# you could say --keep here too\n    $ git checkout topic/wip ;# and then continue\n    $ git stash pop ;# with the local changes\n\nThe branch/reset/checkout sequence itself, either with hard or keep, looks\nmore like a contrived example to show \"reset\" than the best way to solve\nthe problem in the scenario presented there.  Probably we would want to\ndrop this one altogether, or keep the scenario and explain the best\nsolution in somewhere else (e.g. tutorial).\n\n> @@ -163,7 +163,7 @@ Undo commits permanently::\n>  +\n>  ------------\n>  $ git commit ...\n> -$ git reset --hard HEAD~3   <1>\n> +$ git reset --keep HEAD~3   <1>\n>  ------------\n>  +\n>  <1> The last three commits (HEAD, HEAD^, and HEAD~2) were bad\n\nPlease tell a story where keep makes more sense than hard by enhancing the\nexplanatory text <1> associated with this section.  The current text says\nthat the three topmost commit representing what you have recently worked\nso far are all unwanted, strongly hinting that hard is more appropriate\nthing to do than keep, which is not what we want if we are changing the\nexample to use keep.\n\nIt would be sufficient to just hint that the uncommitted changes that you\nhave in your working tree are unrelated to what these three commits wanted\nto do (e.g. you always keep small changes around, such as debugging\nprintf's and a change to the version string in Makefile---you do not\nintend to commit them and they are unrelated to the commits you are\ndiscarding), and you do want to keep them around if you can.\n"},{"id":"159764","messageId":"4D39C923.20202@workspacewhiz.com","threadId":"24691","inReplyTo":"vpqmxmu2nm3.fsf@bauges.imag.fr","subject":"Re: [PATCH 2/2] Re: rebase -i: explain how to discard all commits","fromName":"Joshua Jensen","fromEmail":"jjensen@workspacewhiz.com","sentAt":"2011-01-21T17:57:55Z","receivedAt":"2011-01-21T17:57:55Z","isPatch":true,"sender":{"key":"jjensen@workspacewhiz.com","avatar":"https://avatars.githubusercontent.com/u/111687?v=4"},"body":"----- Original Message -----\nFrom: Matthieu Moy\nDate: 1/21/2011 10:05 AM\n> Junio C Hamano<gitster@pobox.com>  writes:\n>\n>> Johannes Schindelin<Johannes.Schindelin@gmx.de>  writes:\n>>\n>>>> Wouldn't that suggest us that if we were to do anything to this message\n>>>> it would be a good idea to teach the user to \"reset --hard\" the branch\n>>>> if no commits truly needs to be replayed on top of the onto-commit?\n>>> The important difference between rebase -i&&  noop on the one, and reset\n>>> --hard on the other hand is that the latter is completely unsafe. I mean,\n>>> utterly completely super-unsafe. And I say that because _this here\n>>> developer_ who is not exactly a Git noob lost stuff that way.\n>> I think \"rebase\" already checks that the index and the working tree is\n>> clean before starting, so referring to \"reset --hard\" when \"rebase -i\"\n>> notices there is absolutely nothing to do is _not_ unsafe, no?\n> The point is not about letting rebase do a \"reset --hard\", but to tell\n> the user s/he should have ran \"reset --hard\" instead of rebase. The\n> danger is to teach the user's fingers to type \"reset --hard\" too\n> often, which is unsafe ;-).\nI've always wished \"git reset --hard\" would tell me there are modified \nfiles and force me to type \"git reset --hard --force\" to overwrite \nthem.  It is a dangerous command, and I stupidly run it sometimes \nwithout running \"git status\" first.\n\n-Josh\n"},{"id":"159765","messageId":"20110121183734.GB16325@burratino","threadId":"24691","inReplyTo":"4D39C923.20202@workspacewhiz.com","subject":"[PATCH] Documentation: do not treat reset --keep as a special case","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-01-21T18:37:34Z","receivedAt":"2011-01-21T18:37:34Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"The current treatment of \"git reset --keep\" emphasizes how it\ndiffers from --hard (treatment of local changes) and how it breaks\ndown into plumbing (git read-tree -m -u HEAD <commit> followed by git\nupdate-ref HEAD <commit>).  This can discourage people from using\nit, since it might seem to be a complex or niche option.\n\nBetter to emphasize what the --keep flag is intended for --- moving\nthe index and worktree from one commit to another, like \"git checkout\"\nwould --- so the reader can make a more informed decision about the\nappropriate situations in which to use it.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\nJoshua Jensen wrote:\n\n> I've always wished \"git reset --hard\" would tell me there are\n> modified files and force me to type \"git reset --hard --force\" to\n> overwrite them.  It is a dangerous command, and I stupidly run it\n> sometimes without running \"git status\" first.\n\nHave you tried \"git reset --keep\"?  How does it compare to your\nwish?\n\n Documentation/git-reset.txt |    9 ++-------\n 1 files changed, 2 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt\nindex fd72976..927ecee 100644\n--- a/Documentation/git-reset.txt\n+++ b/Documentation/git-reset.txt\n@@ -76,15 +76,10 @@ In other words, --merge does something like a 'git read-tree -u -m <commit>',\n but carries forward unmerged index entries.\n \n --keep::\n-\tResets the index, updates files in the working tree that are\n-\tdifferent between <commit> and HEAD, but keeps those\n-\twhich are different between HEAD and the working tree (i.e.\n-\twhich have local changes).\n+\tResets index entries and updates files in the working tree that are\n+\tdifferent between <commit> and HEAD.\n \tIf a file that is different between <commit> and HEAD has local changes,\n \treset is aborted.\n-+\n-In other words, --keep does a 2-way merge between <commit> and HEAD followed by\n-'git reset --mixed <commit>'.\n --\n \n If you want to undo a commit other than the latest on a branch,\n-- \n1.7.4.rc2\n"},{"id":"159767","messageId":"20110121191459.GC16325@burratino","threadId":"24691","inReplyTo":"7voc7ap3dp.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Documentation: suggest \"reset --keep\" to undo a commit","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-01-21T19:14:59Z","receivedAt":"2011-01-21T19:14:59Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Junio C Hamano wrote:\n\n> But the user could do the reviewing and thinking with some local changes\n> still in the working tree (they are incredients for the fourth commit yet\n> to be made) and decide to branch at that point.  The description in <1>\n> needs to be updated to hint that there can be uncommitted changes, e.g.\n>\n> \tYou have worked for some time, made a few commits, and may have\n> \tuncommitted changes.  After reviewing the current state, you\n> \trealized that ...\n>\n> Using --keep may help the user do so, but only if the local changes do not\n> conflict with the changes in the recent commits to be discarded, right?\n\nI think this explanation misses out on something.\n\nI may be abusing git in a certain way, but I find myself in the\nfollowing situation fairly often:\n\n\t... hack hack hack ...\n\tgit add -p;\t# hmm, looks like multiple features.\n\tgit stash -k\n\t... test ...\n\tgit commit;\t# commit feature #1\n\tgit stash pop\n\n\tgit add -p\n\tgit stash -k\n\t... test ...\n\tgit commit; # commit feature #2\n\tgit stash pop\n\n\t# hmm, feature #2 is not suitable for this branch.\n\tgit branch wip/feature-2\n\tgit reset --keep HEAD^;\t# <*>\n\tgit add -p\n\tgit stash -k\n\t... test ...\n\tgit commit; # commit feature #3\n\nOn line <*>, I am just not thinking about the uncommitted changes.\nThey may be there or they may not.  If they are in the way of what I\nam trying to do, \"git reset --keep\" will politely inform me so I can\nact accordingly (usually stash, commit, or discard them).\n\n> By the way, a more natural way to do this would actually be:\n>\n>     $ git checkout -b topic/wip\n>     $ git branch -f @{-1} HEAD~3\n\nTrue.  (I think the intended scenario was\n\n\tgit branch topic/wip; # save the tip for later\n\tgit reset --keep HEAD~3\n\t# now what was I working on?\n\t... hack hack hack ...\n\n\t# okay, now we have time for that diversion.\n\tgit checkout topic/wip\n\nbut it would be nice to contrast it with the one you described.)\n\n> or using the stash:\n>\n>     $ git stash ;# save local changes\n>     $ git branch topic/wip ;# and mark the tip before rewinding\n>     $ git reset --hard HEAD~3 ;# you could say --keep here too\n>     $ git checkout topic/wip ;# and then continue\n>     $ git stash pop ;# with the local changes\n\nThis approach leaves more files touched and more targets to be rebuilt\nby \"make\".\n\n> Please tell a story where keep makes more sense than hard by enhancing the\n> explanatory text <1> associated with this section.  The current text says\n> that the three topmost commit representing what you have recently worked\n> so far are all unwanted, strongly hinting that hard is more appropriate\n> thing to do than keep, which is not what we want if we are changing the\n> example to use keep.\n\nMaybe the best story would be \"you have just explored a blind alley\nand decided the last three commits are not a good idea at all\", with\nreference to a new section explaining that\n\n * --soft is for when the commit in preparation has the right content\n   but should be on top of a different parent (e.g., squashing commits)\n\n * --keep is for transporting your local changes to a different commit\n   (e.g., rewinding a branch or transplanting changes)\n\n - --merge is a limited and low-level tool for recovering from a\n   conflicted merge and most often will take ORIG_HEAD as its argument.\n\n   Maybe in the future merges will save more information so reset --merge\n   can error out more often.\n\n - --hard is for resetting to a known state\n\n - --mixed is for resetting to a known state but leaving the worktree\n   alone\n\n> It would be sufficient to just hint that the uncommitted changes that you\n> have in your working tree are unrelated to what these three commits wanted\n> to do (e.g. you always keep small changes around, such as debugging\n> printf's\n\nThat use case is less interesting to me --- it is relatively harmless\nto clobber such content.\n"},{"id":"159768","messageId":"7vbp3aovbi.fsf@alter.siamese.dyndns.org","threadId":"24691","inReplyTo":"20110121191459.GC16325@burratino","subject":"Re: [PATCH] Documentation: suggest \"reset --keep\" to undo a commit","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-01-21T20:28:33Z","receivedAt":"2011-01-21T20:28:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n>> Please tell a story where keep makes more sense than hard by enhancing the\n>> explanatory text <1> associated with this section.  The current text says\n>> that the three topmost commit representing what you have recently worked\n>> so far are all unwanted, strongly hinting that hard is more appropriate\n>> thing to do than keep, which is not what we want if we are changing the\n>> example to use keep.\n>\n> Maybe the best story would be \"you have just explored a blind alley\n> and decided the last three commits are not a good idea at all\", with\n\nThat unfortunately does not seem to describe the nature of the local\nchanges at all, which I think is the whole point of this topic to\nencourage use of --keep over --hard.\n\n>> It would be sufficient to just hint that the uncommitted changes that you\n>> have in your working tree are unrelated to what these three commits wanted\n>> to do (e.g. you always keep small changes around, such as debugging\n>> printf's\n>\n> That use case is less interesting to me --- it is relatively harmless\n> to clobber such content.\n\nActually I think that is the primary use case of the feature, as --keep\nwas done as a parallel to the behaviour of checkout that checks out a\ndifferent branch while keeping local changes.\n"},{"id":"159769","messageId":"7v7hdyov0d.fsf@alter.siamese.dyndns.org","threadId":"24691","inReplyTo":"20110121183734.GB16325@burratino","subject":"Re: [PATCH] Documentation: do not treat reset --keep as a special case","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-01-21T20:35:14Z","receivedAt":"2011-01-21T20:35:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> The current treatment of \"git reset --keep\" emphasizes how it\n> differs from --hard (treatment of local changes) and how it breaks\n> down into plumbing (git read-tree -m -u HEAD <commit> followed by git\n> update-ref HEAD <commit>).  This can discourage people from using\n> it, since it might seem to be a complex or niche option.\n>\n> Better to emphasize what the --keep flag is intended for --- moving\n> the index and worktree from one commit to another, like \"git checkout\"\n> would --- so the reader can make a more informed decision about the\n> appropriate situations in which to use it.\n\nThe updated text makes quite a lot of sense ;-) while the old text\ndoesn't.  What were we smoking when we wrote it and passed it through the\nreview?\n\n> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>\n>  Documentation/git-reset.txt |    9 ++-------\n>  1 files changed, 2 insertions(+), 7 deletions(-)\n>\n> diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt\n> index fd72976..927ecee 100644\n> --- a/Documentation/git-reset.txt\n> +++ b/Documentation/git-reset.txt\n> @@ -76,15 +76,10 @@ In other words, --merge does something like a 'git read-tree -u -m <commit>',\n>  but carries forward unmerged index entries.\n>  \n>  --keep::\n> -\tResets the index, updates files in the working tree that are\n> -\tdifferent between <commit> and HEAD, but keeps those\n> -\twhich are different between HEAD and the working tree (i.e.\n> -\twhich have local changes).\n> +\tResets index entries and updates files in the working tree that are\n> +\tdifferent between <commit> and HEAD.\n>  \tIf a file that is different between <commit> and HEAD has local changes,\n>  \treset is aborted.\n\nI saw \"updates files\" and one question immediately came to mind: update\nhow?  \"... to match what is in HEAD\"?  \"Resets index entries\" is less of a\nproblem as the word \"reset\" already strongly suggests that the current\nstate does not matter as much as the target state, though.\n\nThanks.\n"},{"id":"159803","messageId":"alpine.DEB.1.00.1101232109530.1541@bonsai2","threadId":"24691","inReplyTo":"7vsjwmp5cs.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 2/2] Re: rebase -i: explain how to discard all commits","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2011-01-23T20:10:40Z","receivedAt":"2011-01-23T20:10:40Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 21 Jan 2011, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> >> Wouldn't that suggest us that if we were to do anything to this \n> >> message it would be a good idea to teach the user to \"reset --hard\" \n> >> the branch if no commits truly needs to be replayed on top of the \n> >> onto-commit?\n> >\n> > The important difference between rebase -i && noop on the one, and \n> > reset --hard on the other hand is that the latter is completely \n> > unsafe. I mean, utterly completely super-unsafe. And I say that \n> > because _this here developer_ who is not exactly a Git noob lost stuff \n> > that way.\n> \n> I think \"rebase\" already checks that the index and the working tree is \n> clean before starting, so referring to \"reset --hard\" when \"rebase -i\" \n> notices there is absolutely nothing to do is _not_ unsafe, no?\n\nOh, so you want to suggest using \"reset --hard\" but warn at the same time \nthat this command on its own is dangerous unless you run rebase first? :-)\n\nCiao,\nJohannes\n"},{"id":"159877","messageId":"AANLkTim3jPv1=T49wG5WJu_b947ZE=uNHD_2gjxePAfx@mail.gmail.com","threadId":"24691","inReplyTo":"4D39C923.20202@workspacewhiz.com","subject":"Re: [PATCH 2/2] Re: rebase -i: explain how to discard all commits","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-01-26T07:33:14Z","receivedAt":"2011-01-26T07:33:14Z","isPatch":true,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Fri, Jan 21, 2011 at 12:57 PM, Joshua Jensen\n<jjensen@workspacewhiz.com> wrote:\n> I've always wished \"git reset --hard\" would tell me there are modified files\n> and force me to type \"git reset --hard --force\" to overwrite them.  It is a\n> dangerous command, and I stupidly run it sometimes without running \"git\n> status\" first.\n\nSomething analogous to clean.requireForce?\n\nj.\n"}]}