git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: pre-rebase safety hook

From
Junio C Hamano <gitster@pobox.com>
Date
Dec 4, 2008, 22:29 UTC
Message-ID
<7vd4g7d15r.fsf@gitster.siamese.dyndns.org>
In-Reply-To
<7vbpvrens3.fsf@gitster.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
Show 16 quoted lines
> If you want to prevent a branch whose tip commit is on more than one
> branches from being rebased, I think something like this would suffice.
>
>     #!/bin/sh
>     LF='
>     '
>     in_branches=$(git branch -a --with "${2-HEAD}")
>     case "$in_branches" in
>     *"$LF"*)
> 	: this commit is on more than two branches
>         exit 1
>         ;;
>     esac
>     exit 0
>
> But I didn't test it.

Actually, the above cannot possibly be right. To decide whether to allow rebasing of a branch or not, you need to also give it from which commit the rebase will rewrite.

For example, suppose you have a branch "topic", that was forked from "master" and built two commits, then another branch "side" was forked from that, and you have three more commits on "topic" since then:

               o "side"
              /  
         A---B---C---D---E "topic"
        /
    ---o---o---o---o "master"

Now, can I allow you to rebase "topic"? It depends. These should be allowed:

	git rebase B "topic"
	git rebase C "topic"
	git rebase D "topic"

but rebasing "topic" on top of "master", or anything that changes the fact that "topic" contains commits A and B, should be prohibited, because it will interfere with "side". For example,

	git rebase A "topic"
would make this history:
           B---o "side"
          /
         A---B'--C'--D'--E' "topic"
        /
    ---o---o---o---o "master"
where B' and B are different commits.

So you need to check all the commits that will be affected by the rebase to see if any of them is on a branch other than the one that is being rebased. The set of commits that needs to be checked are:

        git rev-list "$1..${2-HEAD}"

so a naive implementation that is based on brnach --with would probably look like:

	#!/bin/sh
	: allow rebasing a detached HEAD
	git symbolic-ref -q HEAD || exit 0
        LF='
        '
        git rev-list "$1..${2-HEAD}" |
        while read commit
        do
        	case "$(git branch -a --with $commit)" in
                *"$LF"*)
                	: this is on two or more branches
                        exit 1
                        ;;
		esac
	done
Previous: Junio C Hamano
Message 3 of 3 in “pre-rebase safety hook”
  1. Tim HarperDec 4, 2008
  2. Junio C HamanoDec 4, 2008
  3. Junio C HamanoDec 4, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.