3 # Copyright (c) 2006 Junio C Hamano
12 topic
=`git symbolic-ref HEAD`
15 case "$basebranch,$topic" in
16 master
,refs
/heads
/??
/*)
19 exit 0 ;# we do not interrupt others.
23 # Now we are dealing with a topic branch being rebased
24 # on top of master. Is it OK to rebase it?
26 # Is topic fully merged to master?
27 not_in_master
=`git-rev-list --pretty=oneline ^master "$topic"`
28 if test -z "$not_in_master"
30 echo >&2 "$topic is fully merged to master; better remove it."
31 exit 1 ;# we could allow it, but there is no point.
34 # Is topic ever merged to next? If so you should not be rebasing it.
35 only_next_1
=`git-rev-list ^master "^$topic" ${publish} | sort`
36 only_next_2
=`git-rev-list ^master ${publish} | sort`
37 if test "$only_next_1" = "$only_next_2"
39 not_in_topic
=`git-rev-list "^$topic" master`
40 if test -z "$not_in_topic"
42 echo >&2 "$topic is already up-to-date with master"
43 exit 1 ;# we could allow it, but there is no point.
48 not_in_next
=`git-rev-list --pretty=oneline ^${publish} "$topic"`
51 my $msg = "* $topic has commits already merged to public branch:\n";
52 my (%not_in_next) = map {
55 } split(/\n/, $ARGV[1]);
59 } split(/\n/, $ARGV[2])) {
60 if (!exists $not_in_next{$elem->[0]}) {
65 print STDERR " $elem->[1]\n";
68 ' "$topic" "$not_in_next" "$not_in_master"
74 ################################################################
76 This sample hook safeguards topic branches that have been
77 published from being rewound.
79 The workflow assumed here is
:
81 * Once a topic branch forks from
"master", "master" is never
82 merged into it again
(either directly or indirectly
).
84 * Once a topic branch is fully cooked and merged into
"master",
85 it is deleted. If you need to build on top of it to correct
86 earlier mistakes
, a new topic branch is created by forking
at
87 the tip of the
"master". This is not strictly necessary
, but
88 it makes it easier to keep your
history simple.
90 * Whenever you need to
test or publish your changes to topic
91 branches
, merge them into
"next" branch.
93 The
script, being an example
, hardcodes the publish branch name
94 to be
"next", but it is trivial to
make it configurable via
95 $GIT_DIR/config mechanism.
97 With this workflow
, you would want to know
:
99 (1) ...
if a topic branch has ever been merged to
"next". Young
100 topic branches can have stupid mistakes you would rather
101 clean up before publishing
, and things that have not been
102 merged into other branches can be easily rebased without
103 affecting other people. But once it is published
, you would
104 not want to rewind it.
106 (2) ...
if a topic branch has been fully merged to
"master".
107 Then you can delete it. More importantly
, you should not
108 build on top of it
-- other people may already want to
109 change things related to the topic as patches against your
110 "master", so
if you need further changes
, it is better to
111 fork the topic
(perhaps with the same name
) afresh from the
114 Let
's look at this example:
116 o---o---o---o---o---o---o---o---o---o "next"
120 / / c---c---c---c B /
124 ---o---o---o---o---o---o---o---o---o---o---o "master"
127 A, B and C are topic branches.
129 * A has one fix since it was merged up to "next".
131 * B has finished. It has been fully merged up to "master" and "next",
132 and is ready to be deleted.
134 * C has not merged to "next" at all.
136 We would want to allow C to be rebased, refuse A, and encourage
141 git-rev-list ^master ^topic next
142 git-rev-list ^master next
144 if these match, topic has not merged in next at all.
148 git-rev-list master..topic
150 if this is empty, it is fully merged to "master".