3 # Copyright (c) 2006, 2008 Junio C Hamano
5 # The "pre-rebase" hook is run just before "git rebase" starts doing
6 # its job, and can prevent the command from running by exiting with
9 # The hook is called with the following parameters:
11 # $1 -- the upstream the series was forked from.
12 # $2 -- the branch being rebased (or empty when rebasing the current branch).
14 # This sample shows how to prevent topic branches that are already
15 # merged to 'next' branch from getting rebased, because allowing it
16 # would result in rebasing already published history.
24 topic
=`git symbolic-ref HEAD` ||
25 exit 0 ;# we do not interrupt rebasing detached HEAD
32 exit 0 ;# we do not interrupt others.
36 # Now we are dealing with a topic branch being rebased
37 # on top of master. Is it OK to rebase it?
39 # Does the topic really exist?
40 git show-ref
-q "$topic" ||
{
41 echo >&2 "No such branch $topic"
45 # Is topic fully merged to master?
46 not_in_master
=`git rev-list --pretty=oneline ^master "$topic"`
47 if test -z "$not_in_master"
49 echo >&2 "$topic is fully merged to master; better remove it."
50 exit 1 ;# we could allow it, but there is no point.
53 # Is topic ever merged to next? If so you should not be rebasing it.
54 only_next_1
=`git rev-list ^master "^$topic" ${publish} | sort`
55 only_next_2
=`git rev-list ^master ${publish} | sort`
56 if test "$only_next_1" = "$only_next_2"
58 not_in_topic
=`git rev-list "^$topic" master`
59 if test -z "$not_in_topic"
61 echo >&2 "$topic is already up-to-date with master"
62 exit 1 ;# we could allow it, but there is no point.
67 not_in_next
=`git rev-list --pretty=oneline ^${publish} "$topic"`
70 my $msg = "* $topic has commits already merged to public branch:\n";
71 my (%not_in_next) = map {
74 } split(/\n/, $ARGV[1]);
78 } split(/\n/, $ARGV[2])) {
79 if (!exists $not_in_next{$elem->[0]}) {
84 print STDERR " $elem->[1]\n";
87 ' "$topic" "$not_in_next" "$not_in_master"
93 ################################################################
95 This sample hook safeguards topic branches that have been
96 published from being rewound.
98 The workflow assumed here is
:
100 * Once a topic branch forks from
"master", "master" is never
101 merged into it again
(either directly or indirectly
).
103 * Once a topic branch is fully cooked and merged into
"master",
104 it is deleted. If you need to build on top of it to correct
105 earlier mistakes
, a new topic branch is created by forking
at
106 the tip of the
"master". This is not strictly necessary
, but
107 it makes it easier to keep your
history simple.
109 * Whenever you need to
test or publish your changes to topic
110 branches
, merge them into
"next" branch.
112 The
script, being an example
, hardcodes the publish branch name
113 to be
"next", but it is trivial to
make it configurable via
114 $GIT_DIR/config mechanism.
116 With this workflow
, you would want to know
:
118 (1) ...
if a topic branch has ever been merged to
"next". Young
119 topic branches can have stupid mistakes you would rather
120 clean up before publishing
, and things that have not been
121 merged into other branches can be easily rebased without
122 affecting other people. But once it is published
, you would
123 not want to rewind it.
125 (2) ...
if a topic branch has been fully merged to
"master".
126 Then you can delete it. More importantly
, you should not
127 build on top of it
-- other people may already want to
128 change things related to the topic as patches against your
129 "master", so
if you need further changes
, it is better to
130 fork the topic
(perhaps with the same name
) afresh from the
133 Let
's look at this example:
135 o---o---o---o---o---o---o---o---o---o "next"
139 / / c---c---c---c B /
143 ---o---o---o---o---o---o---o---o---o---o---o "master"
146 A, B and C are topic branches.
148 * A has one fix since it was merged up to "next".
150 * B has finished. It has been fully merged up to "master" and "next",
151 and is ready to be deleted.
153 * C has not merged to "next" at all.
155 We would want to allow C to be rebased, refuse A, and encourage
160 git rev-list ^master ^topic next
161 git rev-list ^master next
163 if these match, topic has not merged in next at all.
167 git rev-list master..topic
169 if this is empty, it is fully merged to "master".