{"thread":{"id":"30743","subject":"[PATCH] Warnings before rebasing -i published history","startedAt":"2012-06-07T21:20:53Z","lastAt":"2012-06-12T15:22:59Z","messageCount":25,"participants":["Lucien Kong","Matthieu Moy","Junio C Hamano","konglu@minatec.inpg.fr","Tomas Carnecky","Thomas Rast","Nguy Thomas"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"193115","messageId":"1339104053-7782-1-git-send-email-Lucien.Kong@ensimag.imag.fr","threadId":"30743","inReplyTo":null,"subject":"[PATCH] Warnings before rebasing -i published history","fromName":"Lucien Kong","fromEmail":"lucien.kong@ensimag.imag.fr","sentAt":"2012-06-07T21:20:53Z","receivedAt":"2012-06-07T21:20:53Z","isPatch":true,"sender":{"key":"lucien.kong@ensimag.imag.fr","avatar":null},"body":"\"git rebase -i\" can be very dangerous if used on an already published\nhistory. This code detects that one is rewriting a commit that is an\nancestor of a remote-tracking branch, and warns the user through the\neditor.\n\nSigned-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>\nSigned-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>\nSigned-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>\nSigned-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>\nSigned-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>\nSigned-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>\n---\nFor now, the code only warns the user; he can't revert back to his\noriginal state. We agree with everyone that he should be given a\nway to abort the rebase.\n\n git-rebase--interactive.sh    |   17 +++++++++++++++++\n t/t3404-rebase-interactive.sh |   26 ++++++++++++++++++++++++++\n 2 files changed, 43 insertions(+), 0 deletions(-)\n\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 0c19b7c..67b5faf 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -684,6 +684,20 @@ rearrange_squash () {\n \trm -f \"$1.sq\" \"$1.rearranged\"\n }\n \n+# Add a warning notification at the end of each pick or fixup/squash\n+# line of the todo list, providing the picking commit is already\n+# published.\n+warn_published () {\n+\tcat \"$1\" | while read -r command sha1 message\n+\tdo\n+\t\ttest -n \"$sha1\" || break\n+\t\tif test -n \"$(git branch -r --contains \"$sha1\")\"\n+\t\tthen\n+\t\t\tprintf \"%s\\n\" \"$(sed -e \"/\"$sha1\"/ s|$| [Published]|\" \"$1\")\" >\"$1\"\n+\t\tfi\n+\tdone\n+}\n+\n case \"$action\" in\n continue)\n \t# do we have anything to commit?\n@@ -857,6 +871,7 @@ fi\n \n test -s \"$todo\" || echo noop >> \"$todo\"\n test -n \"$autosquash\" && rearrange_squash \"$todo\"\n+warn_published \"$todo\"\n cat >> \"$todo\" << EOF\n \n # Rebase $shortrevisions onto $shortonto\n@@ -869,6 +884,8 @@ cat >> \"$todo\" << EOF\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 #\n+# Warning: [Published] means that the commit has already been published\n+#\n # These lines can be re-ordered; they are executed from top to bottom.\n #\n # If you remove a line here THAT COMMIT WILL BE LOST.\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 025c1c6..f7c31c1 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -755,4 +755,30 @@ test_expect_success 'rebase-i history with funny messages' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'warn before rewriting published history' '\n+\ttest_when_finished \"rm -rf git.git git\" &&\n+\tgit init git.git &&\n+\tgit clone git &&\n+\t(\n+\t\tcd git &&\n+\t\ttest_commit one_commit main.txt one_commit &&\n+\t\ttest_commit two_commit main.txt two_commit &&\n+\t\ttest_commit three_commit main.txt three_commit &&\n+\t\tgit push --all &&\n+\t\ttest_commit four_commit main.txt four_commit &&\n+\t\tFAKE_LINES=\"1 2 3\" &&\n+\t\texport FAKE_LINES &&\n+\t\ttmp=$(git rebase -i HEAD~3 | sed -n 2,4p) &&\n+\t\techo \"$tmp\" >actual &&\n+\t\ttmp=$(git cherry --abbrev=7 HEAD~3 | sed -e 's/+[[:space:]]//g') &&\n+\t\ttwo_sha1=$(echo \"$tmp\" | sed -n 1p) &&\n+\t\tthree_sha1=$(echo \"$tmp\" | sed -n 2p) &&\n+\t\tfour_sha1=$(echo \"$tmp\" | sed -n 3p) &&\n+\t\techo \"pick $two_sha1 two_commit [Published]\" >expected &&\n+\t\techo \"pick $three_sha1 three_commit [Published]\" >>expected &&\n+\t\techo \"pick $four_sha1 four_commit\" >>expected &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n test_done\n-- \n1.7.8\n"},{"id":"193116","messageId":"vpqy5ny22z5.fsf@bauges.imag.fr","threadId":"30743","inReplyTo":"1339104053-7782-1-git-send-email-Lucien.Kong@ensimag.imag.fr","subject":"Re: [PATCH] Warnings before rebasing -i published history","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2012-06-07T22:04:30Z","receivedAt":"2012-06-07T22:04:30Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:\n\n> For now, the code only warns the user; he can't revert back to his\n> original state. We agree with everyone that he should be given a\n> way to abort the rebase.\n\nHe already has: empty the todo-list in the editor and you're done.\n\n> +warn_published () {\n> +\tcat \"$1\" | while read -r command sha1 message\n> +\tdo\n> +\t\ttest -n \"$sha1\" || break\n> +\t\tif test -n \"$(git branch -r --contains \"$sha1\")\"\n> +\t\tthen\n> +\t\t\tprintf \"%s\\n\" \"$(sed -e \"/\"$sha1\"/ s|$| [Published]|\" \"$1\")\" >\"$1\"\n> +\t\tfi\n> +\tdone\n\nAren't you reading and writing from the same file here? Sounds\ndangerous.\n\nThis appends [Published] to commits that are reachable from a\nremote-tracking branch, but I'm wondering if actually showing the remote\nbranch name wouldn't be better, e.g.\n\npick <id> commit one\n# Commits above this line appear in origin/master\npick <id> commit two\npick <id> commit three\n# Commits above this line appear in origin/next\npick <id> most recent commit\n\n>  test -s \"$todo\" || echo noop >> \"$todo\"\n>  test -n \"$autosquash\" && rearrange_squash \"$todo\"\n> +warn_published \"$todo\"\n\nThat should be configurable.\n\n> @@ -869,6 +884,8 @@ cat >> \"$todo\" << EOF\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>  #\n> +# Warning: [Published] means that the commit has already been published\n\nIt's a pity to show the message unconditionally. If you go this way,\nskip the message if you didn't display [Published].\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"193117","messageId":"7vwr3ieo0i.fsf@alter.siamese.dyndns.org","threadId":"30743","inReplyTo":"1339104053-7782-1-git-send-email-Lucien.Kong@ensimag.imag.fr","subject":"Re: [PATCH] Warnings before rebasing -i published history","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-06-07T22:49:17Z","receivedAt":"2012-06-07T22:49:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:\n\n> +# Add a warning notification at the end of each pick or fixup/squash\n> +# line of the todo list, providing the picking commit is already\n> +# published.\n> +warn_published () {\n> +\tcat \"$1\" | while read -r command sha1 message\n\nMake it a habit to question yourself whenever you cat a single file\nand immediately pipe it to elsewhere, i.e.\n\n\tcat \"$1\" | anything\n\nbecause 99% of the time you are much better off writing\n\n\tanything <\"$1\"\n\ninstead.\n\n> +\tdo\n> +\t\ttest -n \"$sha1\" || break\n> +\t\tif test -n \"$(git branch -r --contains \"$sha1\")\"\n> +\t\tthen\n> +\t\t\tprintf \"%s\\n\" \"$(sed -e \"/\"$sha1\"/ s|$| [Published]|\" \"$1\")\" >\"$1\"\n> +\t\tfi\n> +\tdone\n\nWhat's inside $() looks like it wants to say something like\n\n\tsed -e \"/ $sha1 /s/$/ [Published]/\" \"$1\"\n\nbut it has a few fishy double-quotes that makes it unclear why $sha1\nwants to be outside the quotes.\n\nWhy does it need 'printf \"%s\" $()' in the first place?  Wouldn't\n\n\tsed ... >\"$1\"\n\nsufficient?  You let cat read \"$1\", sed read \"$1\" and then the loop\noverwrite \"$1\", which looks very fishy.\n\nThe logic is merely _guessing_ that the commit could have been\npublished, no?  The particular remote repository the test happens to\nfind may not be for consumption by other people.\n\nI am afraid that doing this would send users a wrong message that is\nunnecessarily alarming, especially the marker says \"Published\" as if\nit were a confirmed fact.\n\nIn short, I am not unsympathetic to the motivation, but I find the\nresulting user experience (mostly the wording) questionable, and I\nam not impressed by the implementation very much.\n"},{"id":"193125","messageId":"20120608093257.Horde.eeddeHwdC4BP0aqpIrqTaVA@webmail.minatec.grenoble-inp.fr","threadId":"30743","inReplyTo":"7vwr3ieo0i.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] Warnings before rebasing -i published history","fromName":"","fromEmail":"konglu@minatec.inpg.fr","sentAt":"2012-06-08T07:32:57Z","receivedAt":"2012-06-08T07:32:57Z","isPatch":true,"sender":{"key":"konglu@minatec.inpg.fr","avatar":null},"body":"\nJunio C Hamano <gitster@pobox.com> a écrit :\n\n>> +\tdo\n>> +\t\ttest -n \"$sha1\" || break\n>> +\t\tif test -n \"$(git branch -r --contains \"$sha1\")\"\n>> +\t\tthen\n>> +\t\t\tprintf \"%s\\n\" \"$(sed -e \"/\"$sha1\"/ s|$| [Published]|\" \"$1\")\" >\"$1\"\n>> +\t\tfi\n>> +\tdone\n>\n> What's inside $() looks like it wants to say something like\n>\n> \tsed -e \"/ $sha1 /s/$/ [Published]/\" \"$1\"\n>\n> but it has a few fishy double-quotes that makes it unclear why $sha1\n> wants to be outside the quotes.\n>\n> Why does it need 'printf \"%s\" $()' in the first place?  Wouldn't\n>\n> \tsed ... >\"$1\"\n> sufficient?\n\nThe fact is that the input of sed is \"$1\" itself. An redirecting the output\nof sed to the same input doesn't seem to work.\n\n> The logic is merely _guessing_ that the commit could have been\n> published, no?  The particular remote repository the test happens to\n> find may not be for consumption by other people.\n>\n> I am afraid that doing this would send users a wrong message that is\n> unnecessarily alarming, especially the marker says \"Published\" as if\n> it were a confirmed fact.\n\nTrue. It would be annoying for people that rewrite consciously published\nhistory. From this point of view, a better idea would be to show the\nremote branch name, as Matthieu suggested, so that the user could know\nwhich branch is involved.\n"},{"id":"193129","messageId":"vpqfwa618zv.fsf@bauges.imag.fr","threadId":"30743","inReplyTo":"20120608093257.Horde.eeddeHwdC4BP0aqpIrqTaVA@webmail.minatec.grenoble-inp.fr","subject":"Re: [PATCH] Warnings before rebasing -i published history","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2012-06-08T08:52:04Z","receivedAt":"2012-06-08T08:52:04Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"konglu@minatec.inpg.fr writes:\n\n> The fact is that the input of sed is \"$1\" itself. An redirecting the output\n> of sed to the same input doesn't seem to work.\n\nNo, reading and writing to the same file usually doesn't work (unless\nyou have a very good reason to do it). But using printf seems weird. It\njust forces the shell to hold the whole output of sed in memory to be\nable to pass it to printf.\n\nIsn't a more conventional way to do that\n\nsed -e '...' \"$1\" >\"$1\".new\nmv \"$1\".new \"$1\"\n\n?\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"193135","messageId":"1339147124-ner-3533@calvin","threadId":"30743","inReplyTo":"vpqfwa618zv.fsf@bauges.imag.fr","subject":"Re: [PATCH] Warnings before rebasing -i published history","fromName":"Tomas Carnecky","fromEmail":"tomas.carnecky@gmail.com","sentAt":"2012-06-08T09:18:44Z","receivedAt":"2012-06-08T09:18:44Z","isPatch":true,"sender":{"key":"tomas.carnecky@gmail.com","avatar":null},"body":"On Fri, 08 Jun 2012 10:52:04 +0200, Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> wrote:\n> Isn't a more conventional way to do that\n> \n> sed -e '...' \"$1\" >\"$1\".new\n> mv \"$1\".new \"$1\"\n> \n> ?\n\nIs sed -i not portable or what is the reason not to use it?\n"},{"id":"193136","messageId":"vpqbokuyx5t.fsf@bauges.imag.fr","threadId":"30743","inReplyTo":"1339147124-ner-3533@calvin","subject":"Re: [PATCH] Warnings before rebasing -i published history","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2012-06-08T09:23:42Z","receivedAt":"2012-06-08T09:23:42Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Tomas Carnecky <tomas.carnecky@gmail.com> writes:\n\n> On Fri, 08 Jun 2012 10:52:04 +0200, Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> wrote:\n>> Isn't a more conventional way to do that\n>> \n>> sed -e '...' \"$1\" >\"$1\".new\n>> mv \"$1\".new \"$1\"\n>> \n>> ?\n>\n> Is sed -i not portable ...\n\nIt's a GNU extension, yes.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"193148","messageId":"20120608160341.Horde.IGByfXwdC4BP0gY9a0fV0PA@webmail.minatec.grenoble-inp.fr","threadId":"30743","inReplyTo":"vpqy5ny22z5.fsf@bauges.imag.fr","subject":"Re: [PATCH] Warnings before rebasing -i published history","fromName":"","fromEmail":"konglu@minatec.inpg.fr","sentAt":"2012-06-08T14:03:41Z","receivedAt":"2012-06-08T14:03:41Z","isPatch":true,"sender":{"key":"konglu@minatec.inpg.fr","avatar":null},"body":"\nMatthieu Moy <Matthieu.Moy@grenoble-inp.fr> a écrit :\n\n>>  test -s \"$todo\" || echo noop >> \"$todo\"\n>>  test -n \"$autosquash\" && rearrange_squash \"$todo\"\n>> +warn_published \"$todo\"\n>\n> That should be configurable.\n\nDo you mean that it should be controlled by a key config (maybe a new\nadvice.*) in the config file ? Or through an option ?\n"},{"id":"193152","messageId":"vpqsje5rid7.fsf@bauges.imag.fr","threadId":"30743","inReplyTo":"20120608160341.Horde.IGByfXwdC4BP0gY9a0fV0PA@webmail.minatec.grenoble-inp.fr","subject":"Re: [PATCH] Warnings before rebasing -i published history","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2012-06-08T14:25:08Z","receivedAt":"2012-06-08T14:25:08Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"konglu@minatec.inpg.fr writes:\n\n> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> a Ã©critÂ :\n>\n>>>  test -s \"$todo\" || echo noop >> \"$todo\"\n>>>  test -n \"$autosquash\" && rearrange_squash \"$todo\"\n>>> +warn_published \"$todo\"\n>>\n>> That should be configurable.\n>\n> Do you mean that it should be controlled by a key config (maybe a new\n> advice.*) in the config file ? Or through an option ?\n\nThat should be a config key, I don't think a user wants to type\n--no-published-warnings each time he doesn't want warnings.\n\nCurrent usage of advice.* is a bit different as it usually talks about\ngit's output on the terminal, but I think added comments in the rebase\ntodolist would be an acceptable use of advice.*.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"193157","messageId":"7v8vfxetuh.fsf@alter.siamese.dyndns.org","threadId":"30743","inReplyTo":"1339147124-ner-3533@calvin","subject":"Re: [PATCH] Warnings before rebasing -i published history","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-06-08T14:55:34Z","receivedAt":"2012-06-08T14:55:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Tomas Carnecky <tomas.carnecky@gmail.com> writes:\n\n> On Fri, 08 Jun 2012 10:52:04 +0200, Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> wrote:\n>> Isn't a more conventional way to do that\n>> \n>> sed -e '...' \"$1\" >\"$1\".new\n>> mv \"$1\".new \"$1\"\n>> \n>> ?\n>\n> Is sed -i not portable or what is the reason not to use it?\n\nIt is a GNUism so it is not portable (check POSIX.1 before asking),\nand that is the reason to avoid it.\n"},{"id":"193158","messageId":"7v4nqletrj.fsf@alter.siamese.dyndns.org","threadId":"30743","inReplyTo":"20120608160341.Horde.IGByfXwdC4BP0gY9a0fV0PA@webmail.minatec.grenoble-inp.fr","subject":"Re: [PATCH] Warnings before rebasing -i published history","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-06-08T14:57:20Z","receivedAt":"2012-06-08T14:57:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"konglu@minatec.inpg.fr writes:\n\n> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> a écrit :\n>\n>>>  test -s \"$todo\" || echo noop >> \"$todo\"\n>>>  test -n \"$autosquash\" && rearrange_squash \"$todo\"\n>>> +warn_published \"$todo\"\n>>\n>> That should be configurable.\n>\n> Do you mean that it should be controlled by a key config (maybe a new\n> advice.*) in the config file ? Or through an option ?\n\nProbably \"[rebase] checkremoterefs\" in .git/config; advice.*\nvariables default to true by convention, and it is not suitable for\na misleading \"feature\" like this one.\n"},{"id":"193294","messageId":"1339409091-28150-1-git-send-email-Lucien.Kong@ensimag.imag.fr","threadId":"30743","inReplyTo":"1339104053-7782-1-git-send-email-Lucien.Kong@ensimag.imag.fr","subject":"[PATCHv2] Warnings before rebasing -i published history","fromName":"Lucien Kong","fromEmail":"lucien.kong@ensimag.imag.fr","sentAt":"2012-06-11T10:04:51Z","receivedAt":"2012-06-11T10:04:51Z","isPatch":false,"sender":{"key":"lucien.kong@ensimag.imag.fr","avatar":null},"body":"\"git rebase -i\" can be very dangerous if used on an already published\nhistory. This code detects that one is rewriting a commit that is an\nancestor of a remote-tracking branch, and warns the user through the\neditor. This feature is controlled by a new config key\nrebase.checkremoterefs.\n\nSigned-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>\nSigned-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>\nSigned-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>\nSigned-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>\nSigned-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>\nSigned-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>\n---\n Documentation/config.txt      |    5 +++++\n Documentation/git-rebase.txt  |    5 +++++\n git-rebase--interactive.sh    |   22 ++++++++++++++++++++++\n git-rebase.sh                 |    2 ++\n t/lib-rebase.sh               |   11 +++++++++++\n t/t3404-rebase-interactive.sh |   29 +++++++++++++++++++++++++++++\n 6 files changed, 74 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 915cb5a..e47f6e0 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1753,6 +1753,11 @@ rebase.stat::\n rebase.autosquash::\n \tIf set to true enable '--autosquash' option by default.\n \n+rebase.checkremoterefs::\n+\tIf it is set to 'true', git rebase -i will show after each\n+\tcommit ancestor of a remote-tracking branch the name of these\n+\tbranches through the editor.\n+\n receive.autogc::\n \tBy default, git-receive-pack will run \"git-gc --auto\" after\n \treceiving data from git-push and updating refs.  You can stop\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 147fa1a..b68a80b 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -208,6 +208,11 @@ rebase.stat::\n rebase.autosquash::\n \tIf set to true enable '--autosquash' option by default.\n \n+rebase.checkremoterefs::\n+\tIf it is set to 'true', git rebase -i will show after each\n+\tcommit ancestor of a remote-tracking branch the name of these\n+\tbranches through the editor.\n+\n OPTIONS\n -------\n <newbase>::\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 0c19b7c..ad6f8a7 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -684,6 +684,27 @@ rearrange_squash () {\n \trm -f \"$1.sq\" \"$1.rearranged\"\n }\n \n+# Add the name the branches after each pick, fixup or squash commit that\n+# is an ancestor of a remote-tracking branch.\n+add_remoterefs () {\n+\twhile read -r command sha1 message\n+\tdo\n+\t\tprintf '%s\\n' \"$command $sha1 $message\"\n+\t\tgit branch -r --contains \"$sha1\" >\"$1.branch\"\n+\t\tif test -s \"$1.branch\"\n+\t\tthen\n+\t\t\tprintf \"# Commit above this line appear in:\"\n+\t\t\twhile read -r branch\n+\t\t\tdo\n+\t\t\t\tprintf \" $branch\"\n+\t\t\tdone <\"$1.branch\"\n+\t\t\tprintf '\\n'\n+\t\tfi\n+\tdone >\"$1.published\" <\"$1\"\n+\tcat \"$1.published\" >\"$1\"\n+\trm -f \"$1.published\" \"$1.branch\"\n+}\n+\n case \"$action\" in\n continue)\n \t# do we have anything to commit?\n@@ -857,6 +878,7 @@ fi\n \n test -s \"$todo\" || echo noop >> \"$todo\"\n test -n \"$autosquash\" && rearrange_squash \"$todo\"\n+test -n \"$checkremoterefs\" && add_remoterefs \"$todo\"\n cat >> \"$todo\" << EOF\n \n # Rebase $shortrevisions onto $shortonto\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex e616737..f8675b5 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -99,7 +99,9 @@ action=\n preserve_merges=\n autosquash=\n keep_empty=\n+checkremoterefs=\n test \"$(git config --bool rebase.autosquash)\" = \"true\" && autosquash=t\n+test \"$(git config --bool rebase.checkremoterefs)\" = \"true\" && checkremoterefs=t\n \n read_basic_state () {\n \thead_name=$(cat \"$state_dir\"/head-name) &&\ndiff --git a/t/lib-rebase.sh b/t/lib-rebase.sh\nindex 6ccf797..4906867 100644\n--- a/t/lib-rebase.sh\n+++ b/t/lib-rebase.sh\n@@ -65,3 +65,14 @@ EOF\n \ttest_set_editor \"$(pwd)/fake-editor.sh\"\n \tchmod a+x fake-editor.sh\n }\n+\n+\n+set_copy_editor () {\n+\techo \"#!$SHELL_PATH\" >editor.sh\n+\tcat >> editor.sh <<\\EOF\n+cat \"$1\" >\"$TODO_DUMP\"\n+EOF\n+\n+\ttest_set_editor \"$(pwd)/editor.sh\"\n+\tchmod a+x editor.sh\n+}\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 025c1c6..f99c0c2 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -755,4 +755,33 @@ test_expect_success 'rebase-i history with funny messages' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'warn before rewriting published history' '\n+\ttest_when_finished \"rm -rf git.git git\" &&\n+\tgit init git.git &&\n+\tgit clone git &&\n+\t(\n+\t\tcd git &&\n+\t\tgit config rebase.checkremoterefs true &&\n+\t\ttest_commit one_commit main.txt one_commit &&\n+\t\ttest_commit two_commit main.txt two_commit &&\n+\t\ttest_commit three_commit main.txt three_commit &&\n+\t\tgit push --all &&\n+\t\ttest_commit four_commit main.txt four_commit &&\n+\t\tset_copy_editor &&\n+\t\tTODO_DUMP=actual EDITOR=./editor.sh git rebase -i HEAD~3 &&\n+\t\ttmp=$(cat actual | sed -n 1,5p) &&\n+\t\techo \"$tmp\" >actual &&\n+\t\ttmp=$(git cherry --abbrev=7 HEAD~3 | sed -e 's/+[[:space:]]//g') &&\n+\t\ttwo_sha1=$(echo \"$tmp\" | sed -n 1p) &&\n+\t\tthree_sha1=$(echo \"$tmp\" | sed -n 2p) &&\n+\t\tfour_sha1=$(echo \"$tmp\" | sed -n 3p) &&\n+\t\techo \"pick $two_sha1 two_commit\" >expected &&\n+\t\techo \"# Commit above this line appear in: origin/master\" >>expected &&\n+\t\techo \"pick $three_sha1 three_commit\" >>expected &&\n+\t\techo \"# Commit above this line appear in: origin/master\" >>expected &&\n+\t\techo \"pick $four_sha1 four_commit\" >>expected &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n test_done\n-- \n1.7.8\n"},{"id":"193298","messageId":"vpq1ulm86dh.fsf@bauges.imag.fr","threadId":"30743","inReplyTo":"1339409091-28150-1-git-send-email-Lucien.Kong@ensimag.imag.fr","subject":"Re: [PATCHv2] Warnings before rebasing -i published history","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2012-06-11T10:55:54Z","receivedAt":"2012-06-11T10:55:54Z","isPatch":false,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:\n\n> \"git rebase -i\" can be very dangerous if used on an already published\n> history. This code detects that one is rewriting a commit that is an\n> ancestor of a remote-tracking branch, and warns the user through the\n> editor. This feature is controlled by a new config key\n> rebase.checkremoterefs.\n\nFor the lazy, you could provide an example of result in the commit\nmessage. People don't want to review how the patch is written if they\ndisagree with the result.\n\n> +\t\ttwo_sha1=$(echo \"$tmp\" | sed -n 1p) &&\n> +\t\tthree_sha1=$(echo \"$tmp\" | sed -n 2p) &&\n> +\t\tfour_sha1=$(echo \"$tmp\" | sed -n 3p) &&\n\nIIRC, the test suite was made to give reproducible sha1, so you\nshouldn't need these.\n\n> +\t\techo \"pick $two_sha1 two_commit\" >expected &&\n> +\t\techo \"# Commit above this line appear in: origin/master\" >>expected &&\n> +\t\techo \"pick $three_sha1 three_commit\" >>expected &&\n> +\t\techo \"# Commit above this line appear in: origin/master\" >>expected &&\n> +\t\techo \"pick $four_sha1 four_commit\" >>expected &&\n> +\t\ttest_cmp expected actual\n\nYou don't want to repeat \"Commit above this line\" for each commit. What\nI meant in my previous suggestion was\n\npick foo\npick bar\n# Commits above this line appear in origin/master\npick boz\n\ni.e. just show where the remote points once.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"193300","messageId":"20120611133618.Horde.ife5dHwdC4BP1dgywnBALiA@webmail.minatec.grenoble-inp.fr","threadId":"30743","inReplyTo":"vpq1ulm86dh.fsf@bauges.imag.fr","subject":"Re: [PATCHv2] Warnings before rebasing -i published history","fromName":"","fromEmail":"konglu@minatec.inpg.fr","sentAt":"2012-06-11T11:36:18Z","receivedAt":"2012-06-11T11:36:18Z","isPatch":false,"sender":{"key":"konglu@minatec.inpg.fr","avatar":null},"body":"\nMatthieu Moy <Matthieu.Moy@grenoble-inp.fr> a écrit :\n\n> Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:\n>\n>> \"git rebase -i\" can be very dangerous if used on an already published\n>> history. This code detects that one is rewriting a commit that is an\n>> ancestor of a remote-tracking branch, and warns the user through the\n>> editor. This feature is controlled by a new config key\n>> rebase.checkremoterefs.\n>\n> For the lazy, you could provide an example of result in the commit\n> message. People don't want to review how the patch is written if they\n> disagree with the result.\n\nRight, but wouldn't it be better to put the example in the doc\ngit-rebase.txt ?\n"},{"id":"193301","messageId":"vpqehpm5b8e.fsf@bauges.imag.fr","threadId":"30743","inReplyTo":"20120611133618.Horde.ife5dHwdC4BP1dgywnBALiA@webmail.minatec.grenoble-inp.fr","subject":"Re: [PATCHv2] Warnings before rebasing -i published history","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2012-06-11T11:39:13Z","receivedAt":"2012-06-11T11:39:13Z","isPatch":false,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"konglu@minatec.inpg.fr writes:\n\n> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> a Ã©critÂ :\n>\n>> Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:\n>>\n>>> \"git rebase -i\" can be very dangerous if used on an already published\n>>> history. This code detects that one is rewriting a commit that is an\n>>> ancestor of a remote-tracking branch, and warns the user through the\n>>> editor. This feature is controlled by a new config key\n>>> rebase.checkremoterefs.\n>>\n>> For the lazy, you could provide an example of result in the commit\n>> message. People don't want to review how the patch is written if they\n>> disagree with the result.\n>\n> Right, but wouldn't it be better to put the example in the doc\n> git-rebase.txt ?\n\nWhy not. In any case, it should be easy to find for reviewers (I had to\ndig a little to find the expected value in the tests).\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"193302","messageId":"87r4tmhy12.fsf_-_@thomas.inf.ethz.ch","threadId":"30743","inReplyTo":"1339409091-28150-1-git-send-email-Lucien.Kong@ensimag.imag.fr","subject":"branch --contains is unbearably slow [Re: [PATCHv2] Warnings before rebasing -i published history]","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2012-06-11T11:46:01Z","receivedAt":"2012-06-11T11:46:01Z","isPatch":false,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"[+Cc Junio who wrote branch --contains, and Peff who sped up tag\n--contains in ffc4b801.]\n\nLucien Kong <Lucien.Kong@ensimag.imag.fr> writes:\n\n> \"git rebase -i\" can be very dangerous if used on an already published\n> history. This code detects that one is rewriting a commit that is an\n> ancestor of a remote-tracking branch, and warns the user through the\n> editor. This feature is controlled by a new config key\n> rebase.checkremoterefs.\n[...]\n> +# Add the name the branches after each pick, fixup or squash commit that\n> +# is an ancestor of a remote-tracking branch.\n> +add_remoterefs () {\n> +\twhile read -r command sha1 message\n> +\tdo\n> +\t\tprintf '%s\\n' \"$command $sha1 $message\"\n> +\t\tgit branch -r --contains \"$sha1\" >\"$1.branch\"\n[...]\n> +\tdone >\"$1.published\" <\"$1\"\n> +\tcat \"$1.published\" >\"$1\"\n> +\trm -f \"$1.published\" \"$1.branch\"\n> +}\n\nWhile I like the idea, I think it unfortunately needs some changes in\n'git branch --contains'.  That command is unbelievably slow on a\nrepository with many remote branches, like my git.git:\n\n  $ g remote -v | wc -l  # note that each appears twice, for fetch/push\n  28\n  $ git branch -r | wc -l\n  364\n\n  $ time git branch -r --contains origin/next\n    origin/next\n\n  real    0m32.060s\n  user    0m31.895s\n  sys     0m0.036s\n\nI think an upper bound for the runtime of any 'git branch --contains'\nshould be generating the *complete* topology like this:\n\n  $ time git log --graph --oneline --all >/dev/null\n\n  real    0m2.637s\n  user    0m2.246s\n  sys     0m0.364s\n\nIt should also be possible to generate the --contains output for several\ncommits at the same time.  Otherwise the feature will be too painfully\nslow for all but the simplest rebases.  Currently the startup time for\n'rebase -i' to show an editor is near-instantaneous for me; adding N*2s\nwould be too much on most of my topics, where I tend to gather a handful\nof fixups and improvements before the next 'rebase -i' round.\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"193322","messageId":"7vvcix7rim.fsf@alter.siamese.dyndns.org","threadId":"30743","inReplyTo":"87r4tmhy12.fsf_-_@thomas.inf.ethz.ch","subject":"Re: branch --contains is unbearably slow [Re: [PATCHv2] Warnings before rebasing -i published history]","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-06-11T16:16:49Z","receivedAt":"2012-06-11T16:16:49Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n>   $ time git branch -r --contains origin/next\n>     origin/next\n>\n>   real    0m32.060s\n>   user    0m31.895s\n>   sys     0m0.036s\n>\n> I think an upper bound for the runtime of any 'git branch --contains'\n> should be generating the *complete* topology like this:\n>\n>   $ time git log --graph --oneline --all >/dev/null\n>\n>   real    0m2.637s\n>   user    0m2.246s\n>   sys     0m0.364s\n\nHrm, there must be something I am doing wrong.\n\n    $ time git log --graph --oneline --all >/dev/null\n\n    real    0m3.896s\n    user    0m3.476s\n    sys     0m0.416s\n\nOk, so my disk is slower than yours, perhaps.  But\n\n    $ time git branch -r --contains next\n      github2/next\n      gph/next\n      ko/next\n      repo/next\n\n    real    0m3.853s\n    user    0m3.804s\n    sys     0m0.048s\n"},{"id":"193392","messageId":"1339451781-29324-1-git-send-email-Lucien.Kong@ensimag.imag.fr","threadId":"30743","inReplyTo":"1339409091-28150-1-git-send-email-Lucien.Kong@ensimag.imag.fr","subject":"[PATCHv3 1/2] Warnings before rebasing -i published history","fromName":"Lucien Kong","fromEmail":"lucien.kong@ensimag.imag.fr","sentAt":"2012-06-11T21:56:20Z","receivedAt":"2012-06-11T21:56:20Z","isPatch":false,"sender":{"key":"lucien.kong@ensimag.imag.fr","avatar":null},"body":"\"git rebase -i\" can be very dangerous if used on an already published\nhistory. This code detects that one is rewriting a commit that is an\nancestor of a remote-tracking branch, and warns the user through the\neditor. This feature is controlled by a new config key\nrebase.checkremoterefs.\n\nHere is an example of the behaviour of this feature:\n\n   pick <id> commit pushed_one\n   # Commits above this line appear in origin/master\n   pick <id> commit pushed_two\n   pick <id> commit pushed_three\n   # Commits above this line appear in origin/next\n   pick <id> commit local\n\nSigned-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>\nSigned-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>\nSigned-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>\nSigned-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>\nSigned-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>\nSigned-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>\n---\nThe remote points are now only shown once. The behavior of\ngit branch --contains is the same than in v2 (not optimized).\n\n Documentation/config.txt      |    5 +++++\n Documentation/git-rebase.txt  |    5 +++++\n git-rebase--interactive.sh    |   32 ++++++++++++++++++++++++++++++++\n git-rebase.sh                 |    2 ++\n t/lib-rebase.sh               |   11 +++++++++++\n t/t3404-rebase-interactive.sh |   27 +++++++++++++++++++++++++++\n 6 files changed, 82 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 915cb5a..e47f6e0 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -1753,6 +1753,11 @@ rebase.stat::\n rebase.autosquash::\n \tIf set to true enable '--autosquash' option by default.\n \n+rebase.checkremoterefs::\n+\tIf it is set to 'true', git rebase -i will show after each\n+\tcommit ancestor of a remote-tracking branch the name of these\n+\tbranches through the editor.\n+\n receive.autogc::\n \tBy default, git-receive-pack will run \"git-gc --auto\" after\n \treceiving data from git-push and updating refs.  You can stop\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 147fa1a..b68a80b 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -208,6 +208,11 @@ rebase.stat::\n rebase.autosquash::\n \tIf set to true enable '--autosquash' option by default.\n \n+rebase.checkremoterefs::\n+\tIf it is set to 'true', git rebase -i will show after each\n+\tcommit ancestor of a remote-tracking branch the name of these\n+\tbranches through the editor.\n+\n OPTIONS\n -------\n <newbase>::\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex 0c19b7c..7e4ae16 100644\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -684,6 +684,37 @@ rearrange_squash () {\n \trm -f \"$1.sq\" \"$1.rearranged\"\n }\n \n+# Add the name of the branches after each pick, fixup or squash commit that\n+# is an ancestor of a remote-tracking branch.\n+add_remoterefs () {\n+\tto_print=\n+\tbranches_name=\n+\twhile read -r command sha1 message\n+\tdo\n+\t\tgit branch -r --contains \"$sha1\" >\"$1.branch\"\n+\t\tif test -s \"$1.branch\"\n+\t\tthen\n+\t\t\twhile read -r branch\n+\t\t\tdo\n+\t\t\t\tbranches_name=\"$branches_name $branch\"\n+\t\t\tdone <\"$1.branch\"\n+\t\tfi\n+\n+\t\tif test \"$to_print\" != \"$branches_name\"\n+\t\tthen\n+\t\t\tif test -n \"$to_print\"\n+\t\t\tthen\n+\t\t\t\tprintf '%s\\n' \"# Commits above this line appear in:$to_print\"\n+\t\t\tfi\n+\t\t\tto_print=$branches_name\n+\t\tfi\n+\t\tbranches_name=\n+\t\tprintf '%s\\n' \"$command $sha1 $message\"\n+\tdone >\"$1.published\" <\"$1\"\n+\tcat \"$1.published\" >\"$1\"\n+\trm -f \"$1.published\" \"$1.branch\"\n+}\n+\n case \"$action\" in\n continue)\n \t# do we have anything to commit?\n@@ -857,6 +888,7 @@ fi\n \n test -s \"$todo\" || echo noop >> \"$todo\"\n test -n \"$autosquash\" && rearrange_squash \"$todo\"\n+test -n \"$checkremoterefs\" && add_remoterefs \"$todo\"\n cat >> \"$todo\" << EOF\n \n # Rebase $shortrevisions onto $shortonto\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex e616737..f8675b5 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -99,7 +99,9 @@ action=\n preserve_merges=\n autosquash=\n keep_empty=\n+checkremoterefs=\n test \"$(git config --bool rebase.autosquash)\" = \"true\" && autosquash=t\n+test \"$(git config --bool rebase.checkremoterefs)\" = \"true\" && checkremoterefs=t\n \n read_basic_state () {\n \thead_name=$(cat \"$state_dir\"/head-name) &&\ndiff --git a/t/lib-rebase.sh b/t/lib-rebase.sh\nindex 6ccf797..4906867 100644\n--- a/t/lib-rebase.sh\n+++ b/t/lib-rebase.sh\n@@ -65,3 +65,14 @@ EOF\n \ttest_set_editor \"$(pwd)/fake-editor.sh\"\n \tchmod a+x fake-editor.sh\n }\n+\n+\n+set_copy_editor () {\n+\techo \"#!$SHELL_PATH\" >editor.sh\n+\tcat >> editor.sh <<\\EOF\n+cat \"$1\" >\"$TODO_DUMP\"\n+EOF\n+\n+\ttest_set_editor \"$(pwd)/editor.sh\"\n+\tchmod a+x editor.sh\n+}\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 025c1c6..72934a5 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -755,4 +755,31 @@ test_expect_success 'rebase-i history with funny messages' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'warn before rewriting published history' '\n+\ttest_when_finished \"rm -rf git.git git\" &&\n+\tgit init git.git &&\n+\tgit clone git &&\n+\t(\n+\t\tcd git &&\n+\t\tgit config rebase.checkremoterefs true &&\n+\t\ttest_commit one_commit main.txt one_commit &&\n+\t\ttest_commit two_commit main.txt two_commit &&\n+\t\ttest_commit three_commit main.txt three_commit &&\n+\t\tgit push --all &&\n+\t\ttest_commit four_commit main.txt four_commit &&\n+\t\tset_copy_editor &&\n+\t\tTODO_DUMP=actual EDITOR=./editor.sh git rebase -i HEAD~3 &&\n+\t\ttmp=$(cat actual | sed -n 1,5p) &&\n+\t\techo \"$tmp\" >actual &&\n+\t\ttwo_sha1=$(git rev-parse --short HEAD~2) &&\n+\t\tthree_sha1=$(git rev-parse --short HEAD~1) &&\n+\t\tfour_sha1=$(git rev-parse --short HEAD) &&\n+\t\techo \"pick $two_sha1 two_commit\" >expected &&\n+\t\techo \"pick $three_sha1 three_commit\" >>expected &&\n+\t\techo \"# Commits above this line appear in: origin/master\" >>expected &&\n+\t\techo \"pick $four_sha1 four_commit\" >>expected &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n test_done\n-- \n1.7.8\n"},{"id":"193391","messageId":"1339451781-29324-2-git-send-email-Lucien.Kong@ensimag.imag.fr","threadId":"30743","inReplyTo":"1339451781-29324-1-git-send-email-Lucien.Kong@ensimag.imag.fr","subject":"[PATCHv3 2/2] Warnings before amending published history","fromName":"Lucien Kong","fromEmail":"lucien.kong@ensimag.imag.fr","sentAt":"2012-06-11T21:56:21Z","receivedAt":"2012-06-11T21:56:21Z","isPatch":false,"sender":{"key":"lucien.kong@ensimag.imag.fr","avatar":null},"body":"This code detects that one is rewriting a commit that is an ancestor\nof a remote-tracking branch with \"git commit --amend\", and warns the\nuser through the editor.\n\nSigned-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr>\nSigned-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr>\nSigned-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr>\nSigned-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr>\nSigned-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr>\nSigned-off-by: Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>\n---\nAt this point, this feature is not controlled by the config key\nrebase.checkremoterefs. Also, the code can only detects the commits\nthat were published on the same current branch.\n\n builtin/commit.c              |   82 ++++++++++++++++++++++++++\n sha1_name.c                   |   95 +++++++-----------------------\n sha1_name.h                   |  130 +++++++++++++++++++++++++++++++++++++++++\n t/t3404-rebase-interactive.sh |   65 ++++++++++++++++++++\n 4 files changed, 298 insertions(+), 74 deletions(-)\n create mode 100644 sha1_name.h\n\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex f43eaaf..53fe120 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -28,6 +28,7 @@\n #include \"submodule.h\"\n #include \"gpg-interface.h\"\n #include \"column.h\"\n+#include \"sha1_name.h\"\n \n static const char * const builtin_commit_usage[] = {\n \t\"git commit [options] [--] <filepattern>...\",\n@@ -584,6 +585,83 @@ static char *cut_ident_timestamp_part(char *string)\n \treturn ket;\n }\n \n+static char *read_line_from_git_path(const char *filename)\n+{\n+\tstruct strbuf buf = STRBUF_INIT;\n+\tFILE *fp = fopen(git_path(\"%s\", filename), \"r\");\n+\tif (!fp) {\n+\t\tstrbuf_release(&buf);\n+\t\treturn NULL;\n+\t}\n+\tstrbuf_getline(&buf, fp, '\\n');\n+\tif (!fclose(fp))\n+\t\treturn strbuf_detach(&buf, NULL);\n+\telse\n+\t\treturn NULL;\n+}\n+\n+static int insert_first_line_file(char *to_write, char *file_to_modify)\n+{\n+\tint c;\n+\tFILE *tmp = tmpfile();\n+\tFILE *file = fopen(file_to_modify, \"r+\");\n+\tif (!file || !tmp)\n+\t\treturn 0;\n+\n+\twhile ((c = fgetc(file)) != EOF)\n+\t\tfputc(c, tmp);\n+\n+\trewind(file);\n+\trewind(tmp);\n+\tfputs(to_write, file);\n+\twhile ((c = fgetc(tmp)) != EOF)\n+\t\tfputc(c, file);\n+\n+\tfclose(tmp);\n+\tfclose(file);\n+\treturn 1;\n+}\n+\n+static int amend_warn_published(void)\n+{\n+\tchar *head_path = read_line_from_git_path(\"HEAD\");\n+\tchar *last_commit_sha1;\n+\tchar remote_path[PATH_MAX] = \"refs/remotes/origin/\";\n+\tchar *remote_branch;\n+\tunsigned char nth_ancestor_remote_sha1[20];\n+\tint i = 0;\n+\n+\tif (!head_path)\n+\t\treturn 0;\n+\n+\tstrtok(head_path, \" \");\n+\tlast_commit_sha1 = read_line_from_git_path(strtok(NULL, \"\"));\n+\tif (!last_commit_sha1)\n+\t\treturn 0;\n+\n+\tremote_branch = read_line_from_git_path(\"HEAD\");\n+\tif (!remote_branch)\n+\t\treturn 0;\n+\n+\tstrtok(remote_branch, \"/\");\n+\tstrtok(NULL, \"/\");\n+\tstrcat(remote_path, strtok(NULL, \"\"));\n+\n+\twhile (!get_nth_ancestor(remote_path, 40, nth_ancestor_remote_sha1, i)) {\n+\t\tif (!strcmp(sha1_to_hex(nth_ancestor_remote_sha1), last_commit_sha1)) {\n+\t\t\tinsert_first_line_file(\"# The commit to reword is already published.\\n\\n\",\n+\t\t\t\t\tgit_path(commit_editmsg));\n+\t\t\tbreak;\n+\t\t}\n+\t\ti++;\n+\t}\n+\n+\tfree(head_path);\n+\tfree(last_commit_sha1);\n+\tfree(remote_branch);\n+\treturn 1;\n+}\n+\n static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\t\t     struct commit *current_head,\n \t\t\t     struct wt_status *s,\n@@ -840,6 +918,10 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\tconst char *env[2] = { NULL };\n \t\tenv[0] =  index;\n \t\tsnprintf(index, sizeof(index), \"GIT_INDEX_FILE=%s\", index_file);\n+\n+\t\tif (amend)\n+\t\t\tamend_warn_published();\n+\n \t\tif (launch_editor(git_path(commit_editmsg), NULL, env)) {\n \t\t\tfprintf(stderr,\n \t\t\t_(\"Please supply the message using either -m or -F option.\\n\"));\ndiff --git a/sha1_name.c b/sha1_name.c\nindex c633113..14a0e96 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -1,4 +1,5 @@\n #include \"cache.h\"\n+#include \"sha1_name.h\"\n #include \"tag.h\"\n #include \"commit.h\"\n #include \"tree.h\"\n@@ -7,9 +8,7 @@\n #include \"refs.h\"\n #include \"remote.h\"\n \n-static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *);\n-\n-static int find_short_object_filename(int len, const char *name, unsigned char *sha1)\n+int find_short_object_filename(int len, const char *name, unsigned char *sha1)\n {\n \tstruct alternate_object_database *alt;\n \tchar hex[40];\n@@ -56,7 +55,7 @@ static int find_short_object_filename(int len, const char *name, unsigned char *\n \treturn found;\n }\n \n-static int match_sha(unsigned len, const unsigned char *a, const unsigned char *b)\n+int match_sha(unsigned len, const unsigned char *a, const unsigned char *b)\n {\n \tdo {\n \t\tif (*a != *b)\n@@ -71,7 +70,7 @@ static int match_sha(unsigned len, const unsigned char *a, const unsigned char *\n \treturn 1;\n }\n \n-static int find_short_packed_object(int len, const unsigned char *match, unsigned char *sha1)\n+int find_short_packed_object(int len, const unsigned char *match, unsigned char *sha1)\n {\n \tstruct packed_git *p;\n \tconst unsigned char *found_sha1 = NULL;\n@@ -130,10 +129,7 @@ static int find_short_packed_object(int len, const unsigned char *match, unsigne\n \treturn found;\n }\n \n-#define SHORT_NAME_NOT_FOUND (-1)\n-#define SHORT_NAME_AMBIGUOUS (-2)\n-\n-static int find_unique_short_object(int len, char *canonical,\n+int find_unique_short_object(int len, char *canonical,\n \t\t\t\t    unsigned char *res, unsigned char *sha1)\n {\n \tint has_unpacked, has_packed;\n@@ -157,7 +153,7 @@ static int find_unique_short_object(int len, char *canonical,\n \treturn 0;\n }\n \n-static int get_short_sha1(const char *name, int len, unsigned char *sha1,\n+int get_short_sha1(const char *name, int len, unsigned char *sha1,\n \t\t\t  int quietly)\n {\n \tint i, status;\n@@ -216,7 +212,7 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len)\n \treturn hex;\n }\n \n-static int ambiguous_path(const char *path, int len)\n+int ambiguous_path(const char *path, int len)\n {\n \tint slash = 1;\n \tint cnt;\n@@ -241,7 +237,7 @@ static int ambiguous_path(const char *path, int len)\n \treturn slash;\n }\n \n-static inline int upstream_mark(const char *string, int len)\n+inline int upstream_mark(const char *string, int len)\n {\n \tconst char *suffix[] = { \"@{upstream}\", \"@{u}\" };\n \tint i;\n@@ -255,9 +251,7 @@ static inline int upstream_mark(const char *string, int len)\n \treturn 0;\n }\n \n-static int get_sha1_1(const char *name, int len, unsigned char *sha1);\n-\n-static int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n+int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n {\n \tstatic const char *warn_msg = \"refname '%.*s' is ambiguous.\";\n \tchar *real_ref = NULL;\n@@ -358,7 +352,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n \treturn 0;\n }\n \n-static int get_parent(const char *name, int len,\n+int get_parent(const char *name, int len,\n \t\t      unsigned char *result, int idx)\n {\n \tunsigned char sha1[20];\n@@ -388,7 +382,7 @@ static int get_parent(const char *name, int len,\n \treturn -1;\n }\n \n-static int get_nth_ancestor(const char *name, int len,\n+int get_nth_ancestor(const char *name, int len,\n \t\t\t    unsigned char *result, int generation)\n {\n \tunsigned char sha1[20];\n@@ -436,7 +430,7 @@ struct object *peel_to_type(const char *name, int namelen,\n \t}\n }\n \n-static int peel_onion(const char *name, int len, unsigned char *sha1)\n+int peel_onion(const char *name, int len, unsigned char *sha1)\n {\n \tunsigned char outer[20];\n \tconst char *sp;\n@@ -522,7 +516,7 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)\n \treturn 0;\n }\n \n-static int get_describe_name(const char *name, int len, unsigned char *sha1)\n+int get_describe_name(const char *name, int len, unsigned char *sha1)\n {\n \tconst char *cp;\n \n@@ -542,7 +536,7 @@ static int get_describe_name(const char *name, int len, unsigned char *sha1)\n \treturn -1;\n }\n \n-static int get_sha1_1(const char *name, int len, unsigned char *sha1)\n+int get_sha1_1(const char *name, int len, unsigned char *sha1)\n {\n \tint ret, has_suffix;\n \tconst char *cp;\n@@ -590,17 +584,7 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1)\n \treturn get_short_sha1(name, len, sha1, 0);\n }\n \n-/*\n- * This interprets names like ':/Initial revision of \"git\"' by searching\n- * through history and returning the first commit whose message starts\n- * the given regular expression.\n- *\n- * For future extension, ':/!' is reserved. If you want to match a message\n- * beginning with a '!', you have to repeat the exclamation mark.\n- */\n-#define ONELINE_SEEN (1u<<20)\n-\n-static int handle_one_ref(const char *path,\n+int handle_one_ref(const char *path,\n \t\tconst unsigned char *sha1, int flag, void *cb_data)\n {\n \tstruct commit_list **list = cb_data;\n@@ -618,7 +602,7 @@ static int handle_one_ref(const char *path,\n \treturn 0;\n }\n \n-static int get_sha1_oneline(const char *prefix, unsigned char *sha1,\n+int get_sha1_oneline(const char *prefix, unsigned char *sha1,\n \t\t\t    struct commit_list *list)\n {\n \tstruct commit_list *backup = NULL, *l;\n@@ -675,12 +659,7 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1,\n \treturn found ? 0 : -1;\n }\n \n-struct grab_nth_branch_switch_cbdata {\n-\tlong cnt, alloc;\n-\tstruct strbuf *buf;\n-};\n-\n-static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,\n+int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,\n \t\t\t\t  const char *email, unsigned long timestamp, int tz,\n \t\t\t\t  const char *message, void *cb_data)\n {\n@@ -704,11 +683,7 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,\n \treturn 0;\n }\n \n-/*\n- * Parse @{-N} syntax, return the number of characters parsed\n- * if successful; otherwise signal an error with negative value.\n- */\n-static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf)\n+int interpret_nth_prior_checkout(const char *name, struct strbuf *buf)\n {\n \tlong nth;\n \tint i, retval;\n@@ -794,27 +769,6 @@ int get_sha1_mb(const char *name, unsigned char *sha1)\n \treturn st;\n }\n \n-/*\n- * This reads short-hand syntax that not only evaluates to a commit\n- * object name, but also can act as if the end user spelled the name\n- * of the branch from the command line.\n- *\n- * - \"@{-N}\" finds the name of the Nth previous branch we were on, and\n- *   places the name of the branch in the given buf and returns the\n- *   number of characters parsed if successful.\n- *\n- * - \"<branch>@{upstream}\" finds the name of the other ref that\n- *   <branch> is configured to merge with (missing <branch> defaults\n- *   to the current branch), and places the name of the branch in the\n- *   given buf and returns the number of characters parsed if\n- *   successful.\n- *\n- * If the input is not of the accepted format, it returns a negative\n- * number to signal an error.\n- *\n- * If the input was ok but there are not N branch switches in the\n- * reflog, it returns 0.\n- */\n int interpret_branch_name(const char *name, struct strbuf *buf)\n {\n \tchar *cp;\n@@ -898,18 +852,13 @@ int strbuf_check_branch_ref(struct strbuf *sb, const char *name)\n \treturn check_refname_format(sb->buf, 0);\n }\n \n-/*\n- * This is like \"get_sha1_basic()\", except it allows \"sha1 expressions\",\n- * notably \"xyz^\" for \"parent of xyz\"\n- */\n int get_sha1(const char *name, unsigned char *sha1)\n {\n \tstruct object_context unused;\n \treturn get_sha1_with_context(name, sha1, &unused);\n }\n \n-/* Must be called only when object_name:filename doesn't exist. */\n-static void diagnose_invalid_sha1_path(const char *prefix,\n+void diagnose_invalid_sha1_path(const char *prefix,\n \t\t\t\t       const char *filename,\n \t\t\t\t       const unsigned char *tree_sha1,\n \t\t\t\t       const char *object_name)\n@@ -946,8 +895,7 @@ static void diagnose_invalid_sha1_path(const char *prefix,\n \t}\n }\n \n-/* Must be called only when :stage:filename doesn't exist. */\n-static void diagnose_invalid_index_path(int stage,\n+void diagnose_invalid_index_path(int stage,\n \t\t\t\t\tconst char *prefix,\n \t\t\t\t\tconst char *filename)\n {\n@@ -1003,7 +951,6 @@ static void diagnose_invalid_index_path(int stage,\n \tfree(fullname);\n }\n \n-\n int get_sha1_with_mode_1(const char *name, unsigned char *sha1, unsigned *mode,\n \t\t\t int only_to_die, const char *prefix)\n {\n@@ -1014,7 +961,7 @@ int get_sha1_with_mode_1(const char *name, unsigned char *sha1, unsigned *mode,\n \treturn ret;\n }\n \n-static char *resolve_relative_path(const char *rel)\n+char *resolve_relative_path(const char *rel)\n {\n \tif (prefixcmp(rel, \"./\") && prefixcmp(rel, \"../\"))\n \t\treturn NULL;\ndiff --git a/sha1_name.h b/sha1_name.h\nnew file mode 100644\nindex 0000000..bdbcecd\n--- /dev/null\n+++ b/sha1_name.h\n@@ -0,0 +1,130 @@\n+#ifndef SHA1_NAME_H\n+#define SHA1_NAME_H\n+\n+#include \"commit.h\"\n+\n+int find_short_object_filename(int len, const char *name, unsigned char *sha1);\n+\n+int match_sha(unsigned len, const unsigned char *a, const unsigned char *b);\n+\n+int find_short_packed_object(int len, const unsigned char *match, unsigned char *sha1);\n+\n+#define SHORT_NAME_NOT_FOUND (-1)\n+#define SHORT_NAME_AMBIGUOUS (-2)\n+\n+int find_unique_short_object(int len, char *canonical,\n+\t\t\t\t    unsigned char *res, unsigned char *sha1);\n+\n+int get_short_sha1(const char *name, int len, unsigned char *sha1,\n+\t\t\t  int quietly);\n+\n+const char *find_unique_abbrev(const unsigned char *sha1, int len);\n+\n+int ambiguous_path(const char *path, int len);\n+\n+inline int upstream_mark(const char *string, int len);\n+\n+int get_sha1_basic(const char *str, int len, unsigned char *sha1);\n+\n+int get_parent(const char *name, int len,\n+\t\t      unsigned char *result, int idx);\n+\n+int get_nth_ancestor(const char *name, int len,\n+\t\t\t    unsigned char *result, int generation);\n+\n+struct object *peel_to_type(const char *name, int namelen,\n+\t\t\t    struct object *o, enum object_type expected_type);\n+\n+int peel_onion(const char *name, int len, unsigned char *sha1);\n+\n+int get_describe_name(const char *name, int len, unsigned char *sha1);\n+\n+int get_sha1_1(const char *name, int len, unsigned char *sha1);\n+\n+/*\n+ * This interprets names like ':/Initial revision of \"git\"' by searching\n+ * through history and returning the first commit whose message starts\n+ * the given regular expression.\n+ *\n+ * For future extension, ':/!' is reserved. If you want to match a message\n+ * beginning with a '!', you have to repeat the exclamation mark.\n+ */\n+#define ONELINE_SEEN (1u<<20)\n+\n+int handle_one_ref(const char *path,\n+\t\tconst unsigned char *sha1, int flag, void *cb_data);\n+\n+int get_sha1_oneline(const char *prefix, unsigned char *sha1,\n+\t\t\t    struct commit_list *list);\n+\n+struct grab_nth_branch_switch_cbdata {\n+\tlong cnt, alloc;\n+\tstruct strbuf *buf;\n+};\n+\n+int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,\n+\t\t\t\t  const char *email, unsigned long timestamp, int tz,\n+\t\t\t\t  const char *message, void *cb_data);\n+\n+/*\n+ * Parse @{-N} syntax, return the number of characters parsed\n+ * if successful; otherwise signal an error with negative value.\n+ */\n+int interpret_nth_prior_checkout(const char *name, struct strbuf *buf);\n+\n+int get_sha1_mb(const char *name, unsigned char *sha1);\n+\n+/*\n+ * This reads short-hand syntax that not only evaluates to a commit\n+ * object name, but also can act as if the end user spelled the name\n+ * of the branch from the command line.\n+ *\n+ * - \"@{-N}\" finds the name of the Nth previous branch we were on, and\n+ *   places the name of the branch in the given buf and returns the\n+ *   number of characters parsed if successful.\n+ *\n+ * - \"<branch>@{upstream}\" finds the name of the other ref that\n+ *   <branch> is configured to merge with (missing <branch> defaults\n+ *   to the current branch), and places the name of the branch in the\n+ *   given buf and returns the number of characters parsed if\n+ *   successful.\n+ *\n+ * If the input is not of the accepted format, it returns a negative\n+ * number to signal an error.\n+ *\n+ * If the input was ok but there are not N branch switches in the\n+ * reflog, it returns 0.\n+ */\n+int interpret_branch_name(const char *name, struct strbuf *buf);\n+\n+int strbuf_branchname(struct strbuf *sb, const char *name);\n+\n+int strbuf_check_branch_ref(struct strbuf *sb, const char *name);\n+\n+/*\n+ * This is like \"get_sha1_basic()\", except it allows \"sha1 expressions\",\n+ * notably \"xyz^\" for \"parent of xyz\"\n+ */\n+int get_sha1(const char *name, unsigned char *sha1);\n+\n+/* Must be called only when object_name:filename doesn't exist. */\n+void diagnose_invalid_sha1_path(const char *prefix,\n+\t\t\t\t       const char *filename,\n+\t\t\t\t       const unsigned char *tree_sha1,\n+\t\t\t\t       const char *object_name);\n+\n+/* Must be called only when :stage:filename doesn't exist. */\n+void diagnose_invalid_index_path(int stage,\n+\t\t\t\t\tconst char *prefix,\n+\t\t\t\t\tconst char *filename);\n+\n+int get_sha1_with_mode_1(const char *name, unsigned char *sha1, unsigned *mode,\n+\t\t\t int only_to_die, const char *prefix);\n+\n+char *resolve_relative_path(const char *rel);\n+\n+int get_sha1_with_context_1(const char *name, unsigned char *sha1,\n+\t\t\t    struct object_context *oc,\n+\t\t\t    int only_to_die, const char *prefix);\n+\n+#endif\ndiff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh\nindex 72934a5..fec448b 100755\n--- a/t/t3404-rebase-interactive.sh\n+++ b/t/t3404-rebase-interactive.sh\n@@ -782,4 +782,69 @@ test_expect_success 'warn before rewriting published history' '\n \t)\n '\n \n+test_expect_success 'warn before rewriting published history: one user' '\n+\ttest_when_finished \"rm -rf git.git git\" &&\n+\tgit init git.git &&\n+\tgit clone git &&\n+\t(\n+\t\tcd git &&\n+\t\tgit config rebase.checkremoterefs true &&\n+\t\ttest_commit one_commit main.txt one_commit &&\n+\t\tgit push --all\n+\t\tset_copy_editor &&\n+\t\tTODO_DUMP=actual EDITOR=./editor.sh git commit --amend &&\n+\t\ttmp=$(cat actual | sed -n 1p) &&\n+\t\techo \"$tmp\" >actual &&\n+\t\techo \"# The commit to reword is already published.\" >expected &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n+test_expect_success 'warn before rewriting published history: several users' '\n+\ttest_when_finished \"rm -rf git.git git1 git2\" &&\n+\tgit init --bare --share git.git &&\n+\tgit clone git.git git1 &&\n+\tgit clone git.git git2 &&\n+\t(\n+\t\tcd git1 &&\n+\t\ttest_commit one_commit main.txt one_commit &&\n+\t\tgit push --all\n+\t) &&\n+\t(\n+\t\tcd git2 &&\n+\t\tgit pull &&\n+\t\ttest_commit two_commit main.txt two_commit &&\n+\t\tgit push --all\n+\t) &&\n+\t(\n+\t\tcd git1 &&\n+\t\tgit config rebase.checkremoterefs true &&\n+\t\tset_copy_editor &&\n+\t\tTODO_DUMP=actual EDITOR=./editor.sh git commit --amend &&\n+\t\ttmp=$(cat actual | sed -n 1p) &&\n+\t\techo \"$tmp\" >actual &&\n+\t\techo \"# The commit to reword is already published.\" >expected &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n+test_expect_success 'warn before rewriting published history: shared branch' '\n+\ttest_when_finished \"rm -rf git.git git\" &&\n+\tgit init git.git &&\n+\tgit clone git &&\n+\t(\n+\t\tcd git &&\n+\t\tgit config rebase.checkremoterefs true &&\n+\t\tgit checkout -b sharedbranch &&\n+\t\ttest_commit one_commit main.txt one_commit &&\n+\t\tgit push --set-upstream origin sharedbranch &&\n+\t\tset_copy_editor &&\n+\t\tTODO_DUMP=actual EDITOR=./editor.sh git commit --amend &&\n+\t\ttmp=$(cat actual | sed -n 1p) &&\n+\t\techo \"$tmp\" >actual &&\n+\t\techo \"# The commit to reword is already published.\" >expected &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n test_done\n-- \n1.7.8\n"},{"id":"193394","messageId":"87vcix8pz5.fsf@thomas.inf.ethz.ch","threadId":"30743","inReplyTo":"7vvcix7rim.fsf@alter.siamese.dyndns.org","subject":"Re: branch --contains is unbearably slow [Re: [PATCHv2] Warnings before rebasing -i published history]","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2012-06-11T22:04:46Z","receivedAt":"2012-06-11T22:04:46Z","isPatch":false,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Thomas Rast <trast@student.ethz.ch> writes:\n>\n>>   $ time git branch -r --contains origin/next\n>>     origin/next\n>>\n>>   real    0m32.060s\n>>\n>> I think an upper bound for the runtime of any 'git branch --contains'\n>> should be generating the *complete* topology like this:\n>>\n>>   $ time git log --graph --oneline --all >/dev/null\n>>\n>>   real    0m2.637s\n>\n> Hrm, there must be something I am doing wrong.\n>\n>     $ time git log --graph --oneline --all >/dev/null\n>\n>     real    0m3.896s\n>\n> Ok, so my disk is slower than yours, perhaps.\n\nThat was all hot cache, so that shouldn't be an issue.\n\n> But\n>\n>     $ time git branch -r --contains next\n>       github2/next\n>       gph/next\n>       ko/next\n>       repo/next\n>\n>     real    0m3.853s\n\nI suspect most of your branches are in some way closely related to next,\nwhile I have a lot of cruft fetched from all sorts of people that fell\nbehind over the years.  Can you try\n\n  git for-each-ref refs/remotes/ |\n  while read sha tp ref; do\n    printf \"%8d %8d %s\\n\" $(\n      git rev-list --left-right --count $ref...next\n    ) $ref\n  done\n\nFor me the output is as listed below (I ran it with origin/next instead\nof next).  Note that for almost all of them, a naive merge-base walk\n(going back from both until a common commit is found) has to walk\nthousands of commits.\n\nI'll get rid of all this cruft now, but this command doesn't scale in\nthe direction I'm abusing it :-)\n\n    1027    29494 refs/remotes/alt-git/html\n       0     2349 refs/remotes/alt-git/maint\n     921    29494 refs/remotes/alt-git/man\n       0     2245 refs/remotes/alt-git/master\n      27     2191 refs/remotes/alt-git/next\n      80     2130 refs/remotes/alt-git/pu\n     922    29494 refs/remotes/alt-git/todo\n       1     6232 refs/remotes/avar/Makefile-add-CC-to-TRACK_CFLAGS\n     121     6615 refs/remotes/avar/a2c5c4b-broke-tracking-info-test\n      92     4508 refs/remotes/avar/ab/i18n\n     164     5961 refs/remotes/avar/ab/i18n-WIP\n      65     6280 refs/remotes/avar/ab/i18n-add-translations\n      43     2430 refs/remotes/avar/ab/i18n-all\n      78     6275 refs/remotes/avar/ab/i18n-all-continue\n      78     6275 refs/remotes/avar/ab/i18n-all-continue-squash\n      78     5098 refs/remotes/avar/ab/i18n-c-_-only\n      93     6240 refs/remotes/avar/ab/i18n-continue\n      93     6248 refs/remotes/avar/ab/i18n-continue-hi.po\n      99     6269 refs/remotes/avar/ab/i18n-continue-more\n      94     6240 refs/remotes/avar/ab/i18n-continue-with-hindi\n     170     5114 refs/remotes/avar/ab/i18n-docs\n     161     6069 refs/remotes/avar/ab/i18n-even-more\n      92     6232 refs/remotes/avar/ab/i18n-for-junio\n      98     6228 refs/remotes/avar/ab/i18n-for-junio-with-docs\n     162     6069 refs/remotes/avar/ab/i18n-german\n      63     6280 refs/remotes/avar/ab/i18n-gettextize\n     140     6191 refs/remotes/avar/ab/i18n-in-pu\n     160     6123 refs/remotes/avar/ab/i18n-libcharset\n       1     4463 refs/remotes/avar/ab/i18n-missing-Q_-pot-target\n       7     4463 refs/remotes/avar/ab/i18n-more-gettextize\n       9     3008 refs/remotes/avar/ab/i18n-po\n       2     5880 refs/remotes/avar/ab/i18n-prereqs\n     159     6191 refs/remotes/avar/ab/i18n-rebase-out-bugs\n     160     6191 refs/remotes/avar/ab/i18n-rewrite\n     161     6191 refs/remotes/avar/ab/i18n-rewrite-with-po-line-numbers\n      54     3977 refs/remotes/avar/ab/i18n-sh-only\n       1     2397 refs/remotes/avar/ab/i18n-slimmed\n     161     5880 refs/remotes/avar/ab/i18n-squashed\n     140     6228 refs/remotes/avar/ab/i18n-v2\n       8     6123 refs/remotes/avar/ab/icase-directory\n       8     6123 refs/remotes/avar/ab/icase-directory-v2\n       4     3804 refs/remotes/avar/ab/jk/tag-contains\n       1     5782 refs/remotes/avar/add-HTTPS_PROXY-env-variable-to-docs\n     134     6338 refs/remotes/avar/add-fallback-bsd-printf-and-revert-107880a\n       2     5092 refs/remotes/avar/add-missing-const\n       1     5114 refs/remotes/avar/add-platform-specific-tweaks\n     127     6615 refs/remotes/avar/another-test-dont-skip-but-prereq\n     127     6615 refs/remotes/avar/another-test-dont-skip-but-prereq-v2\n       6     7501 refs/remotes/avar/avar/cvsserver-pserver-auth-support\n      26     2591 refs/remotes/avar/avar/fe-fixes\n       2     2430 refs/remotes/avar/avar/fixup-gettext-poison-breakage\n       1     5098 refs/remotes/avar/avar/git-cherry-example\n       1     7776 refs/remotes/avar/avar/git-commit-allow-empty-message\n       1     7689 refs/remotes/avar/avar/git-commit-synopsis-no-allow-empty\n       0     7909 refs/remotes/avar/avar/git-config.d\n       1     7576 refs/remotes/avar/avar/git-svn-no-yoda\n       3     5092 refs/remotes/avar/avar/gitweb-513-warnings\n       5     3829 refs/remotes/avar/avar/jk/tag-contains\n       1     7351 refs/remotes/avar/avar/makefile-remove-INSTLIBDIR\n       3     5203 refs/remotes/avar/avar/minor-patches-to-t-t5400-send-pack.sh\n       3     2430 refs/remotes/avar/avar/nuke-pointless-unsigned-comparisons\n       1     2430 refs/remotes/avar/avar/pull-rebase-config\n       1     3504 refs/remotes/avar/avar/tag-contains-skew\n       6     7576 refs/remotes/avar/avar/test-tap\n       2     7491 refs/remotes/avar/avar/usr-bin-env-not-usr-bin-perl\n       3     6743 refs/remotes/avar/better-test-prereq-handling\n      66     6454 refs/remotes/avar/blah-poison\n       1     7016 refs/remotes/avar/builtin-fetch-errors-to-stderr\n       2     6191 refs/remotes/avar/bump-perl-to-5.8\n       1     6781 refs/remotes/avar/clang\n       2     7165 refs/remotes/avar/cvs-pass\n      69     6454 refs/remotes/avar/debug-gettext-poison\n     143     6338 refs/remotes/avar/disable-gettext-by-default-in-releases\n     217     6773 refs/remotes/avar/dont-be-quiet-under-tap\n      50     6607 refs/remotes/avar/dont-run-todo-in-t0000-basic\n     164     6533 refs/remotes/avar/dont-run-todo-in-t0000-basic-v2\n     102     6439 refs/remotes/avar/dont-run-todo-in-t0000-basic-v3\n     134     6615 refs/remotes/avar/fix-multiple-prereq-bug\n     134     6615 refs/remotes/avar/fix-multiple-prereq-bug-v2\n       1     4508 refs/remotes/avar/fix-poison-for-head-is-now-at\n     192     6894 refs/remotes/avar/forgot-old-git-gettext-v5\n     192     6894 refs/remotes/avar/forgot-old-git-gettext-v6\n      49     6800 refs/remotes/avar/forgot-old-git-gettext-v7-ontop-of-pu-fixup-RHEL-error\n       1     6692 refs/remotes/avar/friendlier-git-reset-mixed-deprecated-message\n       1     6692 refs/remotes/avar/friendlier-git-reset-mixed-deprecated-message-v2\n      49     6800 refs/remotes/avar/gettext\n     129     6296 refs/remotes/avar/gettext-pu\n     128     6270 refs/remotes/avar/gettext-remove-old-sanity-test\n     154     6270 refs/remotes/avar/gettextize-git-in-german\n     127     6279 refs/remotes/avar/gettextize-git-mainporcelain\n     153     6270 refs/remotes/avar/gettextize-git-mainporcelain-even-more\n     127     6270 refs/remotes/avar/gettextize-git-mainporcelain-more\n     144     6338 refs/remotes/avar/gettextize-git-mainporcelain-v2\n     144     6338 refs/remotes/avar/gettextize-git-mainporcelain-v3\n     143     6338 refs/remotes/avar/gettextize-git-mainporcelain-with-perl\n       1     7501 refs/remotes/avar/git-am-allow-leading-whitespace\n       3     6714 refs/remotes/avar/git-am-ignore-whitespace-before-patches\n      25     6746 refs/remotes/avar/git-am-ignore-whitespace-before-patches-v2\n       1     7587 refs/remotes/avar/git-config.d-glob\n       1     7909 refs/remotes/avar/git-config.d-hack\n       6     6815 refs/remotes/avar/git-cover\n       7     6815 refs/remotes/avar/git-cover-2\n       7     6815 refs/remotes/avar/git-cover-3\n     142     6591 refs/remotes/avar/git-cvsimport-alarm-on-while\n       1     6228 refs/remotes/avar/git-send-email-use-catfile\n      98     6711 refs/remotes/avar/git-smoke\n      99     6711 refs/remotes/avar/git-smoke-v2\n      99     6711 refs/remotes/avar/git-smoke-v3\n      99     6664 refs/remotes/avar/git-smoke-v4\n      99     6664 refs/remotes/avar/git-smoke-v5\n     102     6664 refs/remotes/avar/git-smoke-v6\n       1     7501 refs/remotes/avar/git-submodule-toplevel\n       1     7501 refs/remotes/avar/gitignore-patches\n       1     5114 refs/remotes/avar/gitignore-test-mktemp\n       1     6837 refs/remotes/avar/gnu-regex-lib\n     909    29494 refs/remotes/avar/html\n       1     3911 refs/remotes/avar/i18n-synopsis\n       1     6743 refs/remotes/avar/imap-send-clang-warnings\n     151     6591 refs/remotes/avar/in-progress-dont-depend-on-perl\n     142     6591 refs/remotes/avar/internal-error-regression-test\n     145     6553 refs/remotes/avar/internal-error-regression-test-v2\n     121     6615 refs/remotes/avar/lib-git-svn-use-PERL_PATH\n       0     8073 refs/remotes/avar/maint\n       1     6069 refs/remotes/avar/make-autoconf-failure-warning\n       1     5961 refs/remotes/avar/makefile-move-platform-specific-tweaks-above-lib_h-and-lib_objs\n     815    29494 refs/remotes/avar/man\n      93     4508 refs/remotes/avar/master\n      78     6731 refs/remotes/avar/merge-dir-to-symlink-todo-test\n     127     6342 refs/remotes/avar/minor-gettext-infrastructure-fixes\n     142     6591 refs/remotes/avar/mkdir-test-results-on-smoking\n       1     2430 refs/remotes/avar/more-grep-cpus\n     185     6925 refs/remotes/avar/my-next\n     127     6615 refs/remotes/avar/my-pu\n       1     6123 refs/remotes/avar/netbsd-S_IFREG-warning\n       1     6123 refs/remotes/avar/netbsd-S_IFREG-warning-v2\n      44     6607 refs/remotes/avar/next\n       1     6781 refs/remotes/avar/perl-makefile-install-base\n     150     6610 refs/remotes/avar/perl-makefile-install-base-v2-onto-pu\n     148     4952 refs/remotes/avar/pu\n     121     6615 refs/remotes/avar/run-partial-expensive-git-notes-test-everywhere\n     131     6615 refs/remotes/avar/run-partial-expensive-git-notes-test-everywhere-v2\n       1     6765 refs/remotes/avar/run-tests-as-root\n       4     6743 refs/remotes/avar/run-tests-as-root-v2\n      16     6128 refs/remotes/avar/send-email-perl-cleanup\n      16     6128 refs/remotes/avar/send-email-perl-cleanup-v2\n      99     6439 refs/remotes/avar/squash-compat-regex-warnings-sent-to-gawk-maintainer\n     186     6925 refs/remotes/avar/submodule-add-f-on-add\n      86     7119 refs/remotes/avar/sun-studio-12-builtin-notes\n      99     6439 refs/remotes/avar/svn-fe-test-x\n      27     6796 refs/remotes/avar/t/doc-config-extraction\n     161     6533 refs/remotes/avar/t3507-cherry-pick-conflict-sh-error\n       1     6069 refs/remotes/avar/t5560-http-backend-noserver-export-fix\n       1     5092 refs/remotes/avar/t7500-commit.sh-use-test_cmp-instead-of-test\n     139     6228 refs/remotes/avar/temp\n      99     6232 refs/remotes/avar/temp-swedish\n     160     6533 refs/remotes/avar/test-fixes\n     134     6615 refs/remotes/avar/test-intra-progress-using-tap-subtests\n     136     6615 refs/remotes/avar/test-intra-progress-using-tap-subtests-v2\n       1     6894 refs/remotes/avar/test-lib-no-test-results-under-harness\n     121     6615 refs/remotes/avar/test-lib-no-test-results-under-harness-v2\n     126     6338 refs/remotes/avar/test-lib-use-subshell-instead-of-chdir-back\n     119     7202 refs/remotes/avar/test-tap-onto-next\n     170     6997 refs/remotes/avar/test-tap-onto-next-v4\n     170     6997 refs/remotes/avar/test-tap-onto-next-v5\n     171     6997 refs/remotes/avar/test-tap-onto-next-v6\n     171     6997 refs/remotes/avar/test-tap-onto-next-v7\n     193     6925 refs/remotes/avar/test-tap-readme-docs-v1\n     193     6925 refs/remotes/avar/test-tap-readme-docs-v2\n     217     6773 refs/remotes/avar/tests-remove-no-python\n       1     6228 refs/remotes/avar/tests-use-test-cmp-instead-of-diff-1\n     712    29494 refs/remotes/avar/todo\n       2     7347 refs/remotes/avar/topic/gettext\n       9     7347 refs/remotes/avar/topic/gettext-rewrote-translations-out-of-infrastructure-work\n       2     7342 refs/remotes/avar/topic/git-gettext\n       7     7347 refs/remotes/avar/topic/git-gettext-squashed\n       2     7250 refs/remotes/avar/topic/git-gettext-v10\n       2     7250 refs/remotes/avar/topic/git-gettext-v11\n       2     7347 refs/remotes/avar/topic/git-gettext-v6\n       2     7347 refs/remotes/avar/topic/git-gettext-v7\n       2     7342 refs/remotes/avar/topic/git-gettext-v8\n       2     7342 refs/remotes/avar/topic/git-gettext-v9\n       1     6123 refs/remotes/avar/turn-test-expect-code-into-a-function\n       1     6123 refs/remotes/avar/turn-test-expect-code-into-a-function-v2\n       1     6123 refs/remotes/avar/turn-test-expect-code-into-a-function-v3\n      47     6607 refs/remotes/avar/update-fallback-regex-engine\n      47     6607 refs/remotes/avar/update-fallback-regex-engine-v2\n      49     6607 refs/remotes/avar/update-fallback-regex-engine-v3\n      45     6607 refs/remotes/avar/update-index-after-running-pre-commit-hook\n       1     6553 refs/remotes/avar/use-builtin-h-for-builtin-commands\n       1     6280 refs/remotes/avar/use-builtin-h-for-builtin-commands-v2\n     173     5092 refs/remotes/avar/wip/ab/i18n\n     151     6591 refs/remotes/avar/yet-another-test-dont-skip-but-prereq\n     150     6610 refs/remotes/avar/your-vsnprintf-is-broken\n      15    11483 refs/remotes/bigfiles/master\n      65     7016 refs/remotes/byang/diff-range\n      52     7256 refs/remotes/byang/diff-range-split\n      29     6815 refs/remotes/byang/line-log\n      19     6815 refs/remotes/byang/line-log-rebasing\n       1     6932 refs/remotes/byang/master\n      43     6692 refs/remotes/byang/mc-detect\n      48     6692 refs/remotes/byang/mc-detect-2\n      24     6932 refs/remotes/byang/parent-rewrite\n      26     6925 refs/remotes/byang/parent-rewrite-rebase\n      29     6815 refs/remotes/byang/parent-rewrite-submmiting\n      26     7256 refs/remotes/byang/playaround\n      19     6815 refs/remotes/byang/rebasing-p2\n      20     6815 refs/remotes/byang/rebasing-p3\n      18     6692 refs/remotes/byang/rebasing-p4\n      14     6932 refs/remotes/byang/round2\n      14     6894 refs/remotes/byang/round2-fix\n      19     6692 refs/remotes/byang/series-1\n      49     6692 refs/remotes/byang/series-2\n      13     7016 refs/remotes/byang/submitting\n       4     1048 refs/remotes/de-po/maint\n       1      596 refs/remotes/de-po/master\n       2    11826 refs/remotes/dscho/2gb\n     130    11252 refs/remotes/dscho/add-e\n     127    15429 refs/remotes/dscho/after-1.5.5\n     206    29494 refs/remotes/dscho/blog\n       4    18539 refs/remotes/dscho/branchnewworkdir\n    1008    17197 refs/remotes/dscho/builtin-fast-export\n     974    17250 refs/remotes/dscho/builtin-merge-one-file\n      57    15850 refs/remotes/dscho/builtin-remote\n      59    15219 refs/remotes/dscho/color-words\n     971    17250 refs/remotes/dscho/cover-letter\n    2512     6301 refs/remotes/dscho/devel\n       2    16599 refs/remotes/dscho/diff-no-stdout\n       4     9756 refs/remotes/dscho/diff-submodule-summary\n     131    11252 refs/remotes/dscho/diffopts\n     158     9715 refs/remotes/dscho/enhance_git_diff_for_submodules\n    1040    16827 refs/remotes/dscho/execv-builtin\n      74    15799 refs/remotes/dscho/fast-make-doc\n     143    10261 refs/remotes/dscho/grafts\n      20    12474 refs/remotes/dscho/hardlinks\n       1    17820 refs/remotes/dscho/hpux\n      42    10104 refs/remotes/dscho/junio/next\n     143     9736 refs/remotes/dscho/log-rewrap\n       7    29494 refs/remotes/dscho/logos\n       2    16377 refs/remotes/dscho/lstat\n     139    15090 refs/remotes/dscho/mailsplit\n       3     7794 refs/remotes/dscho/master\n     272    11983 refs/remotes/dscho/mob\n      28    13909 refs/remotes/dscho/my-master\n     252    12054 refs/remotes/dscho/my-next\n     679    29494 refs/remotes/dscho/my-todo\n     158    12336 refs/remotes/dscho/name-objects\n     291    12547 refs/remotes/dscho/notes\n     106    14892 refs/remotes/dscho/nul-fix\n      28    14636 refs/remotes/dscho/parseopt\n      43    12424 refs/remotes/dscho/patience\n      77    11536 refs/remotes/dscho/percent-branch\n       4    29494 refs/remotes/dscho/presentations\n     973    17259 refs/remotes/dscho/push-mirror\n     118    12170 refs/remotes/dscho/rebase-early\n     137    12170 refs/remotes/dscho/rebase-i-p\n     107    12177 refs/remotes/dscho/rebase-i-submodule\n      32     9715 refs/remotes/dscho/remote-hg\n     140    15022 refs/remotes/dscho/sanitize-submodules\n     111    10334 refs/remotes/dscho/shortlog-toy\n     148    12006 refs/remotes/dscho/submodule\n     150     9715 refs/remotes/dscho/submodule-summary\n     256     8329 refs/remotes/dscho/tmp\n       8    22811 refs/remotes/dscho/utf8\n     118    12177 refs/remotes/dscho/valgrind\n    2132     6925 refs/remotes/dscho/work/msvc-fixes\n       0     2249 refs/remotes/mhagger/master\n      51     2249 refs/remotes/mhagger/ref-api-D\n      15     2638 refs/remotes/mhagger/refname-full\n       2     3600 refs/remotes/mhagger/refperf\n       0      218 refs/remotes/origin/HEAD\n    1100    29494 refs/remotes/origin/html\n       0      861 refs/remotes/origin/maint\n     980    29494 refs/remotes/origin/man\n       0      218 refs/remotes/origin/master\n       0        0 refs/remotes/origin/next\n     100      200 refs/remotes/origin/pu\n    1012    29494 refs/remotes/origin/todo\n       1     1845 refs/remotes/peff/git2-attrs\n       1     1225 refs/remotes/peff/jk/blame-tree\n       2     1225 refs/remotes/peff/jk/builtin-attr\n      14     1225 refs/remotes/peff/jk/bundle-fetch\n       1     1225 refs/remotes/peff/jk/byte-diff\n       7     1225 refs/remotes/peff/jk/cache-patch-id\n       1     1225 refs/remotes/peff/jk/child-cleanup\n       1     1225 refs/remotes/peff/jk/commits-notes-wip\n       1     1225 refs/remotes/peff/jk/config-sources\n       0     1225 refs/remotes/peff/jk/dash-tests\n       1     1225 refs/remotes/peff/jk/describe\n       2     1225 refs/remotes/peff/jk/diff-highlight\n       1     1224 refs/remotes/peff/jk/dumpstat\n       3     1225 refs/remotes/peff/jk/envirostat\n       3     1225 refs/remotes/peff/jk/fast-commit-list\n       1     1225 refs/remotes/peff/jk/fetch-tracking\n       4     1225 refs/remotes/peff/jk/follow-multiple-wip\n       1     1225 refs/remotes/peff/jk/format-patch-fix\n       9     1225 refs/remotes/peff/jk/generations\n       1     1225 refs/remotes/peff/jk/leading-symlinks\n       1     4203 refs/remotes/peff/jk/maint-ignore-have\n       5     1225 refs/remotes/peff/jk/metadata-cache\n       1     1225 refs/remotes/peff/jk/pager\n       1     1225 refs/remotes/peff/jk/pager-subcommand\n       1     1225 refs/remotes/peff/jk/pretty-nul\n       1     1225 refs/remotes/peff/jk/read-tree-content-merge\n       1     1225 refs/remotes/peff/jk/reflog-rewind\n       0     1225 refs/remotes/peff/jk/remote-helper-disconnect\n       4     1225 refs/remotes/peff/jk/rename-progress\n       1     1225 refs/remotes/peff/jk/repack-alternates\n       1     1225 refs/remotes/peff/jk/sockstats\n       3     1225 refs/remotes/peff/jk/stash-apply-p\n       0     1225 refs/remotes/peff/jk/stream-filter\n       1     1225 refs/remotes/peff/jk/stupid-git-tricks\n       2     1225 refs/remotes/peff/jk/unreachable-archive-loosen\n     106    29494 refs/remotes/peff/meta\n     217     1218 refs/remotes/peff/private\n       1    13904 refs/remotes/sbeyer/extern\n       6    12486 refs/remotes/sbeyer/leaks\n     465    10238 refs/remotes/sbeyer/master\n     454    10238 refs/remotes/sbeyer/mob\n     454    10238 refs/remotes/sbeyer/seq-builtin-dev\n      24    10238 refs/remotes/sbeyer/seq-builtin-rfc\n       7    14109 refs/remotes/sbeyer/seq-proto-rfc\n       0    10146 refs/remotes/spearce/maint\n       0     9760 refs/remotes/spearce/master\n     145     9719 refs/remotes/spearce/next\n     189     9714 refs/remotes/spearce/pu\n     520    29494 refs/remotes/spearce/todo\n     131      368 refs/remotes/tgummerer/index-v5\n       0     1099 refs/remotes/tgummerer/maint\n      65      368 refs/remotes/tgummerer/master\n       0      678 refs/remotes/tgummerer/next\n      91      737 refs/remotes/tgummerer/pu\n     118      368 refs/remotes/tgummerer/pythonprototype\n     986    29494 refs/remotes/tgummerer/todo\n      15       52 refs/remotes/trast-github/line-log-WIP\n      33     1598 refs/remotes/trast-github/line-log-cleanup\n       0     1776 refs/remotes/trast-github/maint\n       0     1686 refs/remotes/trast-github/master\n     204     1216 refs/remotes/trast-github/next\n      61     1590 refs/remotes/trast-github/pu\n     184     1257 refs/remotes/trast-github/t/dangerous-linus-style-xdl-hash\n      11     1224 refs/remotes/trast-github/t/perf-gather-post-1.7.10\n       1     1224 refs/remotes/trast-github/t/proper-xdl-speedup\n     944    29494 refs/remotes/trast-github/todo\n       1      524 refs/remotes/trast-github/tr/darwin-xdl-fast-hash\n       1     1139 refs/remotes/trast-github/tr/inotify-POC\n       1     1224 refs/remotes/trast-github/tr/xdiff-fast-hash\n       1    10853 refs/remotes/trast/LOCAL/completion\n      16     9520 refs/remotes/trast/js/rebase-i-p\n       2    10317 refs/remotes/trast/lh/traverse-gitlinks-on-master\n      33     1598 refs/remotes/trast/line-log-cleanup\n       7    12377 refs/remotes/trast/master\n     178     7157 refs/remotes/trast/next\n     509    29494 refs/remotes/trast/notes/full\n     415    29494 refs/remotes/trast/notes/terse\n       6     6815 refs/remotes/trast/t/color-porcelain-message-output\n      25     6796 refs/remotes/trast/t/doc-config-extraction\n       3     6046 refs/remotes/trast/t/doc-config-extraction-v2\n     243     5264 refs/remotes/trast/t/gfb-both-submodule-features\n     240     5264 refs/remotes/trast/t/gfb-remap-submodules\n       2     5331 refs/remotes/trast/t/gfb-split-submodule\n      32     2191 refs/remotes/trast/t/perf-framework\n      38     2191 refs/remotes/trast/t/sha1_file-parallel-with-perf-framework\n     264     2295 refs/remotes/trast/tr/alternate-grep-userdiff-parallel\n       1     1224 refs/remotes/trast/tr/xdiff-fast-hash\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"193395","messageId":"87bokp8ptd.fsf@thomas.inf.ethz.ch","threadId":"30743","inReplyTo":"87vcix8pz5.fsf@thomas.inf.ethz.ch","subject":"Re: branch --contains is unbearably slow [Re: [PATCHv2] Warnings before rebasing -i published history]","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2012-06-11T22:08:14Z","receivedAt":"2012-06-11T22:08:14Z","isPatch":false,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Thomas Rast <trast@student.ethz.ch> writes:\n\n>> But\n>>\n>>     $ time git branch -r --contains next\n>>       github2/next\n>>       gph/next\n>>       ko/next\n>>       repo/next\n>>\n>>     real    0m3.853s\n[...]\n> I'll get rid of all this cruft now, but this command doesn't scale in\n> the direction I'm abusing it :-)\n\nBTW, my original point still stands: at nearly 4s per invocation of\n'branch -r --contains', the loop as written by Lucien\n\n> +add_remoterefs () {\n> +\twhile read -r command sha1 message\n> +\tdo\n> +\t\tprintf '%s\\n' \"$command $sha1 $message\"\n> +\t\tgit branch -r --contains \"$sha1\" >\"$1.branch\"\n[...]\n> +\tdone >\"$1.published\" <\"$1\"\n> +\tcat \"$1.published\" >\"$1\"\n> +\trm -f \"$1.published\" \"$1.branch\"\n> +}\n\nis unusable in your repository, too.  Which is a real pity, it's a nice\nidea.\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"193404","messageId":"7v8vft5u29.fsf@alter.siamese.dyndns.org","threadId":"30743","inReplyTo":"87vcix8pz5.fsf@thomas.inf.ethz.ch","subject":"Re: branch --contains is unbearably slow [Re: [PATCHv2] Warnings before rebasing -i published history]","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-06-11T23:04:46Z","receivedAt":"2012-06-11T23:04:46Z","isPatch":false,"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 suspect most of your branches are in some way closely related to next,\n> while I have a lot of cruft fetched from all sorts of people that fell\n> behind over the years.  Can you try\n>\n>   git for-each-ref refs/remotes/ |\n>   while read sha tp ref; do\n>     printf \"%8d %8d %s\\n\" $(\n>       git rev-list --left-right --count $ref...next\n>     ) $ref\n>   done\n>\n> For me the output is as listed below (I ran it with origin/next instead\n> of next).  Note that for almost all of them, a naive merge-base walk\n> (going back from both until a common commit is found) has to walk\n> thousands of commits.\n\nI too seem to have a lot of cruft I'd better get rid of.  Thanks for\nreminding ;-).\n\n$ git for-each-ref refs/remotes/ |\n  while read sha tp ref; do\n    printf \"%8d %8d %s\\n\" $(\n      git rev-list --left-right --count $ref...next\n    ) $ref\n  done\n     159     6180 refs/remotes/ab-i18n/i18n\n      65     6284 refs/remotes/ab-i18n/i18n-add-translations\n      63     6279 refs/remotes/ab-i18n/i18n-all\n      93     6244 refs/remotes/ab-i18n/i18n-all-continue\n      78     6279 refs/remotes/ab-i18n/i18n-all-continue-squash\n      93     6244 refs/remotes/ab-i18n/i18n-continue\n      94     6244 refs/remotes/ab-i18n/i18n-continue-with-hindi\n      92     6236 refs/remotes/ab-i18n/i18n-for-junio\n      98     6236 refs/remotes/ab-i18n/i18n-for-junio-with-docs\n      63     6284 refs/remotes/ab-i18n/i18n-gettextize\n     140     6195 refs/remotes/ab-i18n/i18n-in-pu\n     160     6195 refs/remotes/ab-i18n/i18n-rewrite\n     161     6195 refs/remotes/ab-i18n/i18n-rewrite-with-po-line-numbers\n     140     6232 refs/remotes/ab-i18n/i18n-v2\n       0    16335 refs/remotes/gfi/HEAD\n       0    17824 refs/remotes/gfi/maint\n       0    16335 refs/remotes/gfi/master\n      31    20748 refs/remotes/gfi/sp/pack4\n       7    16320 refs/remotes/gfi/sp/sendpack-sideband\n       3    20518 refs/remotes/gfi/sp/splitpack\n       2    16325 refs/remotes/gfi/sp/unixsock\n       0    28459 refs/remotes/git-gui/maint\n       0    28446 refs/remotes/git-gui/master\n       3    28459 refs/remotes/git-gui/pu\n       9    29498 refs/remotes/git-gui/todo\n       0    15622 refs/remotes/git-p4/git-p4\n       0      752 refs/remotes/git-svn/HEAD\n       0     3782 refs/remotes/git-svn/instaweb\n       0      752 refs/remotes/git-svn/master\n       0      753 refs/remotes/git-svn/origin\n       0    13207 refs/remotes/git-svn/spearce/origin\n       0     6744 refs/remotes/git-svn/webrick\n       0      865 refs/remotes/github2/maint\n       0      222 refs/remotes/github2/master\n       0        4 refs/remotes/github2/next\n     100      204 refs/remotes/github2/pu\n     981    29498 refs/remotes/github2/todo\n       0      865 refs/remotes/gph/maint\n       0      222 refs/remotes/gph/master\n       0        4 refs/remotes/gph/next\n     100      204 refs/remotes/gph/pu\n     871    29498 refs/remotes/gph/todo\n       8    16603 refs/remotes/jbf-um/HEAD\n       3    17804 refs/remotes/jbf-um/better-whitespace-checks\n      12    18132 refs/remotes/jbf-um/docwork-concepts\n       1    18010 refs/remotes/jbf-um/docwork-design\n       1    17849 refs/remotes/jbf-um/docwork-detached\n       1    18010 refs/remotes/jbf-um/docwork-foreign-scms\n       1    17883 refs/remotes/jbf-um/docwork-recovery\n       0    17825 refs/remotes/jbf-um/maint\n      10    17867 refs/remotes/jbf-um/maint-history\n       8    16603 refs/remotes/jbf-um/master\n       1    17804 refs/remotes/jbf-um/messages\n       1    19546 refs/remotes/jbf-um/parallel-diff\n       7    20685 refs/remotes/jbf-um/recovery\n       1    21989 refs/remotes/jbf-um/tutorial-2\n      48     3056 refs/remotes/ko-private/jch\n       0     3656 refs/remotes/ko-private/maint\n       5    22527 refs/remotes/ko-private/maint-1.4.4\n       0    16075 refs/remotes/ko-private/maint-1.5.4\n       0    15296 refs/remotes/ko-private/maint-1.5.5\n       0    14555 refs/remotes/ko-private/maint-1.5.6\n       0    11606 refs/remotes/ko-private/maint-1.6.2\n       0     9484 refs/remotes/ko-private/maint-1.6.5\n       0     8014 refs/remotes/ko-private/maint-1.7.0\n       0     7333 refs/remotes/ko-private/maint-1.7.1\n       0     6657 refs/remotes/ko-private/maint-1.7.2\n       0     6616 refs/remotes/ko-private/master\n     175     3056 refs/remotes/ko-private/next\n       0     3171 refs/remotes/ko-private/origin\n      66     8872 refs/remotes/ko-private/private-jch\n      99     3027 refs/remotes/ko-private/pu\n       0     8016 refs/remotes/ko-private/snap\n       0    11942 refs/remotes/ko-private/test\n       0      865 refs/remotes/ko/maint\n       0      222 refs/remotes/ko/master\n       0        4 refs/remotes/ko/next\n     100      204 refs/remotes/ko/pu\n       0     1188 refs/remotes/l10n/master\n       9    14815 refs/remotes/lea/master\n       0    14877 refs/remotes/lea/origin\n       0    18037 refs/remotes/mergetool/master\n       0    18037 refs/remotes/mergetool/mergetool\n     918    13101 refs/remotes/mingw/master\n     862    15327 refs/remotes/mingw/master-borked\n       0    18173 refs/remotes/pasky.web/master\n     825    18172 refs/remotes/pasky.web/mob\n       4    18173 refs/remotes/pasky.web/next\n       8    18173 refs/remotes/pasky.web/pu\n       0    28975 refs/remotes/paulus/HEAD\n       6    29067 refs/remotes/paulus/asdf\n       0    28989 refs/remotes/paulus/dev\n      17    29331 refs/remotes/paulus/lines\n       0    28975 refs/remotes/paulus/master\n      32    29321 refs/remotes/paulus/new\n    1100    29498 refs/remotes/repo/html\n       0      865 refs/remotes/repo/maint\n     980    29498 refs/remotes/repo/man\n       0      222 refs/remotes/repo/master\n       0        4 refs/remotes/repo/next\n     100      204 refs/remotes/repo/pu\n     894    29498 refs/remotes/repo/todo\n       0    13638 refs/remotes/spearce.git/maint\n       0    13207 refs/remotes/spearce.git/master\n     149    13176 refs/remotes/spearce.git/next\n     381    29498 refs/remotes/spearce.git/todo\n       0    28540 refs/remotes/thoyts/maint\n       0    28511 refs/remotes/thoyts/master\n       0    28527 refs/remotes/thoyts/pu\n       9    29498 refs/remotes/thoyts/todo\n       0     8920 refs/remotes/trast-doc/HEAD\n       0     8920 refs/remotes/trast-doc/for-next\n       0     8920 refs/remotes/trast-doc/master\n       0     8917 refs/remotes/trast-doc/pu\n:\n"},{"id":"193418","messageId":"vpqvcixyoed.fsf@bauges.imag.fr","threadId":"30743","inReplyTo":"1339451781-29324-2-git-send-email-Lucien.Kong@ensimag.imag.fr","subject":"Re: [PATCHv3 2/2] Warnings before amending published history","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2012-06-12T07:34:18Z","receivedAt":"2012-06-12T07:34:18Z","isPatch":false,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:\n\n>  builtin/commit.c              |   82 ++++++++++++++++++++++++++\n>  sha1_name.c                   |   95 +++++++-----------------------\n>  sha1_name.h                   |  130 +++++++++++++++++++++++++++++++++++++++++\n\nI'm surprised that you need such a big patch. Basically, you're making\nall static functions in sha1_name.c public. If you really need such\nintrusive change, then you should at least explain why in the commit\nmessage, and most preferably split the patch into one refactoring patch\nto expose the functions and one to use them.\n\nBut I suspect what you're looking for is already in cache.h.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"193419","messageId":"4FD6F384.6050800@gmail.com","threadId":"30743","inReplyTo":"1339451781-29324-1-git-send-email-Lucien.Kong@ensimag.imag.fr","subject":"Re: [PATCHv3 1/2] Warnings before rebasing -i published history","fromName":"Nguy Thomas","fromEmail":"thomasxnguy@gmail.com","sentAt":"2012-06-12T07:45:08Z","receivedAt":"2012-06-12T07:45:08Z","isPatch":false,"sender":{"key":"thomasxnguy@gmail.com","avatar":null},"body":"Le 11/06/2012 23:56, Lucien Kong a écrit :\n> +# Add the name of the branches after each pick, fixup or squash commit that\n> +# is an ancestor of a remote-tracking branch.\n> +add_remoterefs () {\n> +\tto_print=\n> +\tbranches_name=\n> +\twhile read -r command sha1 message\n> +\tdo\n> +\t\tgit branch -r --contains \"$sha1\">\"$1.branch\"\n> +\t\tif test -s \"$1.branch\"\n> +\t\tthen\n> +\t\t\twhile read -r branch\n> +\t\t\tdo\n> +\t\t\t\tbranches_name=\"$branches_name $branch\"\n> +\t\t\tdone<\"$1.branch\"\n> +\t\tfi\n> +\n> +\t\tif test \"$to_print\" != \"$branches_name\"\n> +\t\tthen\n> +\t\t\tif test -n \"$to_print\"\n> +\t\t\tthen\n> +\t\t\t\tprintf '%s\\n' \"# Commits above this line appear in:$to_print\"\n> +\t\t\tfi\n> +\t\t\tto_print=$branches_name\n> +\t\tfi\n> +\t\tbranches_name=\n> +\t\tprintf '%s\\n' \"$command $sha1 $message\"\n> +\tdone>\"$1.published\"<\"$1\"\n> +\tcat \"$1.published\">\"$1\"\n> +\trm -f \"$1.published\" \"$1.branch\"\n> +}\n>\nHum, this function doesn't consider the last commit.\nIt will be fixed.\n"},{"id":"193453","messageId":"7vzk88367g.fsf@alter.siamese.dyndns.org","threadId":"30743","inReplyTo":"vpqvcixyoed.fsf@bauges.imag.fr","subject":"Re: [PATCHv3 2/2] Warnings before amending published history","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-06-12T15:22:59Z","receivedAt":"2012-06-12T15:22:59Z","isPatch":false,"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> Lucien Kong <Lucien.Kong@ensimag.imag.fr> writes:\n>\n>>  builtin/commit.c              |   82 ++++++++++++++++++++++++++\n>>  sha1_name.c                   |   95 +++++++-----------------------\n>>  sha1_name.h                   |  130 +++++++++++++++++++++++++++++++++++++++++\n>\n> I'm surprised that you need such a big patch. Basically, you're making\n> all static functions in sha1_name.c public. If you really need such\n> intrusive change, then you should at least explain why in the commit\n> message, and most preferably split the patch into one refactoring patch\n> to expose the functions and one to use them.\n>\n> But I suspect what you're looking for is already in cache.h.\n\nI do not think I am going to take this nor the rebase patch that\nbases its decision on the hardcoded \"Does the commit appear in the\nhistory of refs/remotes/*anything*?\" logic.\n\nAt least, there should be \"Here is a list of the branches I promised\nothers that I am not to going to rewind.\" even if you are going to\nmake its default value to be \"for-each-ref refs/remotes/\".  It is\ntoo inflexible to be useful otherwise.  Not only in the contributor\nand integrator workflow, but a simple \"Alice asks Bob to pull from\nher Github repository\" will be hurt on the \"I fixed up the issues\nyou raised. Could you please take another look\" round.  Besides, I\nwon't be able to amend things outside 'next' but are in 'pu' ;-).\n\nThe logic in the patch in this thread to check each ref~$n is not\neven worth commenting on, but as to the logic in the other \"rebase\"\none, I think it is wasteful to ask \"what are the refs that can reach\nthis commit?\" when what you really want to know is \"is there any ref\namong this set that can reach this commit?\" (the former needs to\nkeep a lot more state).  It should be something like looking at the\noutput of:\n\n\tgit rev-list <list commits you are going to touch here> \\\n\t\t--not <list tips of refs you have published>\n\nand make sure all the commits you are going to touch appear in the\nresult.  Any missing one is reachable from the refs you have\npublished and you may not want to rebase.\n\nIt may be an interesting thought experiment to see if you can take\nadvantage of the inherent ancestry relationship among the list of\ncommits you are going to touch. The later commits that will be\nreplayed in a rebase are very likely to be children of earlier one,\nso in theory, if you can identify the set of topologically earliest\ncommits that will be replayed, you only need to check them, and if\nyou can cheaply come up with that set of earliest commits, the above\nrev-list may become cheaper.\n"}]}