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 This sample hook safeguards topic branches that have been
94 published from being rewound.
96 The workflow assumed here is
:
98 * Once a topic branch forks from
"master", "master" is never
99 merged into it again
(either directly or indirectly
).
101 * Once a topic branch is fully cooked and merged into
"master",
102 it is deleted. If you need to build on top of it to correct
103 earlier mistakes
, a new topic branch is created by forking
at
104 the tip of the
"master". This is not strictly necessary
, but
105 it makes it easier to keep your
history simple.
107 * Whenever you need to
test or publish your changes to topic
108 branches
, merge them into
"next" branch.
110 The
script, being an example
, hardcodes the publish branch name
111 to be
"next", but it is trivial to
make it configurable via
112 $GIT_DIR/config mechanism.
114 With this workflow
, you would want to know
:
116 (1) ...
if a topic branch has ever been merged to
"next". Young
117 topic branches can have stupid mistakes you would rather
118 clean up before publishing
, and things that have not been
119 merged into other branches can be easily rebased without
120 affecting other people. But once it is published
, you would
121 not want to rewind it.
123 (2) ...
if a topic branch has been fully merged to
"master".
124 Then you can delete it. More importantly
, you should not
125 build on top of it
-- other people may already want to
126 change things related to the topic as patches against your
127 "master", so
if you need further changes
, it is better to
128 fork the topic
(perhaps with the same name
) afresh from the
131 Let
's look at this example:
133 o---o---o---o---o---o---o---o---o---o "next"
137 / / c---c---c---c B /
141 ---o---o---o---o---o---o---o---o---o---o---o "master"
144 A, B and C are topic branches.
146 * A has one fix since it was merged up to "next".
148 * B has finished. It has been fully merged up to "master" and "next",
149 and is ready to be deleted.
151 * C has not merged to "next" at all.
153 We would want to allow C to be rebased, refuse A, and encourage
158 git rev-list ^master ^topic next
159 git rev-list ^master next
161 if these match, topic has not merged in next at all.
165 git rev-list master..topic
167 if this is empty, it is fully merged to "master".