{"thread":{"id":"16597","subject":"pre-rebase safety hook","startedAt":"2008-12-04T17:58:41Z","lastAt":"2008-12-04T22:29:52Z","messageCount":3,"participants":["Tim Harper","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"97157","messageId":"e1a5e9a00812040958u3af4c69ofba66567baacb79c@mail.gmail.com","threadId":"16597","inReplyTo":null,"subject":"pre-rebase safety hook","fromName":"Tim Harper","fromEmail":"timcharper@gmail.com","sentAt":"2008-12-04T17:58:41Z","receivedAt":"2008-12-04T17:58:41Z","isPatch":false,"sender":{"key":"timcharper@gmail.com","avatar":"https://gravatar.com/avatar/1a2e0c06c7862ff065ee6b1d53195333a5a0577c040ecb2856a150d8e0b00ecd?d=mp&s=160"},"body":"Is anyone aware of a pre-rebase hook script that will prevent (or at\nleast warn) you from letting a rebase rewrite a commit that has been\npushed or merged into any branch except it's own?\n\nI've activated the pre-rebase.sample, and it does seem to give me any\nwarnings at all:\n\nHere's the terminal output demonstrating what I mean:\n\nhttp://pastie.org/331082\n\nThanks!\n\nTim\n"},{"id":"97165","messageId":"7vbpvrens3.fsf@gitster.siamese.dyndns.org","threadId":"16597","inReplyTo":"e1a5e9a00812040958u3af4c69ofba66567baacb79c@mail.gmail.com","subject":"Re: pre-rebase safety hook","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-12-04T19:35:56Z","receivedAt":"2008-12-04T19:35:56Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Tim Harper\" <timcharper@gmail.com> writes:\n\n> Is anyone aware of a pre-rebase hook script that will prevent (or at\n> least warn) you from letting a rebase rewrite a commit that has been\n> pushed or merged into any branch except it's own?\n>\n> I've activated the pre-rebase.sample, and it does seem to give me any\n> warnings at all:\n>\n> Here's the terminal output demonstrating what I mean:\n>\n> http://pastie.org/331082\n\nThe example script starts like this:\n\n    #!/bin/sh\n    # ...\n    # This sample shows how to prevent topic branches that are already\n    # merged to 'next' branch from getting rebased, because allowing it\n    # would result in rebasing already published history.\n\nAs it says, it explicitly checks against 'next'.\n\nThe sample was written way before \"branch --with\" feature was added, and I\nsuspect what it does can be expressed more concisely in modern git.\n\n\nIf you want to prevent a branch whose tip commit is on more than one\nbranches from being rebased, I think something like this would suffice.\n\n    #!/bin/sh\n    LF='\n    '\n    in_branches=$(git branch -a --with \"${2-HEAD}\")\n    case \"$in_branches\" in\n    *\"$LF\"*)\n\t: this commit is on more than two branches\n        exit 1\n        ;;\n    esac\n    exit 0\n\nBut I didn't test it.\n"},{"id":"97176","messageId":"7vd4g7d15r.fsf@gitster.siamese.dyndns.org","threadId":"16597","inReplyTo":"7vbpvrens3.fsf@gitster.siamese.dyndns.org","subject":"Re: pre-rebase safety hook","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-12-04T22:29:52Z","receivedAt":"2008-12-04T22:29:52Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> If you want to prevent a branch whose tip commit is on more than one\n> branches from being rebased, I think something like this would suffice.\n>\n>     #!/bin/sh\n>     LF='\n>     '\n>     in_branches=$(git branch -a --with \"${2-HEAD}\")\n>     case \"$in_branches\" in\n>     *\"$LF\"*)\n> \t: this commit is on more than two branches\n>         exit 1\n>         ;;\n>     esac\n>     exit 0\n>\n> But I didn't test it.\n\nActually, the above cannot possibly be right.  To decide whether to allow\nrebasing of a branch or not, you need to also give it from which commit\nthe rebase will rewrite.\n\nFor example, suppose you have a branch \"topic\", that was forked from\n\"master\" and built two commits, then another branch \"side\" was forked from\nthat, and you have three more commits on \"topic\" since then:\n\n               o \"side\"\n              /  \n         A---B---C---D---E \"topic\"\n        /\n    ---o---o---o---o \"master\"\n\nNow, can I allow you to rebase \"topic\"?  It depends.  These should be\nallowed:\n\n\tgit rebase B \"topic\"\n\tgit rebase C \"topic\"\n\tgit rebase D \"topic\"\n\nbut rebasing \"topic\" on top of \"master\", or anything that changes the fact\nthat \"topic\" contains commits A and B, should be prohibited, because it\nwill interfere with \"side\".  For example,\n\n\tgit rebase A \"topic\"\n\nwould make this history:\n\n           B---o \"side\"\n          /\n         A---B'--C'--D'--E' \"topic\"\n        /\n    ---o---o---o---o \"master\"\n\nwhere B' and B are different commits.\n\nSo you need to check all the commits that will be affected by the rebase\nto see if any of them is on a branch other than the one that is being\nrebased.  The set of commits that needs to be checked are:\n\n        git rev-list \"$1..${2-HEAD}\"\n\nso a naive implementation that is based on brnach --with would probably\nlook like:\n\n\t#!/bin/sh\n\n\t: allow rebasing a detached HEAD\n\tgit symbolic-ref -q HEAD || exit 0\n\n        LF='\n        '\n        git rev-list \"$1..${2-HEAD}\" |\n        while read commit\n        do\n        \tcase \"$(git branch -a --with $commit)\" in\n                *\"$LF\"*)\n                \t: this is on two or more branches\n                        exit 1\n                        ;;\n\t\tesac\n\tdone\n"}]}