blob: 6d3eb8ed00e1779efce8abe201d37c8cff07ec29 [file] [log] [blame]
Junio C Hamano0868a302008-07-22 09:20:441From: Junio C Hamano <gitster@pobox.com>
Junio C Hamano63636e52006-02-12 13:31:392Subject: Separating topic branches
3Abstract: In this article, JC describes how to separate topic branches.
4
5This text was originally a footnote to a discussion about the
6behaviour of the git diff commands.
7
8Often I find myself doing that [running diff against something other
9than HEAD] while rewriting messy development history. For example, I
10start doing some work without knowing exactly where it leads, and end
11up with a history like this:
12
13 "master"
14 o---o
Junio C Hamanoa77a5132007-06-08 16:13:4415 \ "topic"
Junio C Hamano63636e52006-02-12 13:31:3916 o---o---o---o---o---o
17
18At this point, "topic" contains something I know I want, but it
19contains two concepts that turned out to be completely independent.
20And often, one topic component is larger than the other. It may
21contain more than two topics.
22
23In order to rewrite this mess to be more manageable, I would first do
24"diff master..topic", to extract the changes into a single patch, start
25picking pieces from it to get logically self-contained units, and
26start building on top of "master":
27
28 $ git diff master..topic >P.diff
29 $ git checkout -b topicA master
30 ... pick and apply pieces from P.diff to build
31 ... commits on topicA branch.
Junio C Hamanoa77a5132007-06-08 16:13:4432
Junio C Hamano63636e52006-02-12 13:31:3933 o---o---o
34 / "topicA"
35 o---o"master"
Junio C Hamanoa77a5132007-06-08 16:13:4436 \ "topic"
Junio C Hamano63636e52006-02-12 13:31:3937 o---o---o---o---o---o
38
39Before doing each commit on "topicA" HEAD, I run "diff HEAD"
40before update-index the affected paths, or "diff --cached HEAD"
41after. Also I would run "diff --cached master" to make sure
42that the changes are only the ones related to "topicA". Usually
43I do this for smaller topics first.
44
45After that, I'd do the remainder of the original "topic", but
46for that, I do not start from the patchfile I extracted by
47comparing "master" and "topic" I used initially. Still on
48"topicA", I extract "diff topic", and use it to rebuild the
49other topic:
50
51 $ git diff -R topic >P.diff ;# --cached also would work fine
52 $ git checkout -b topicB master
53 ... pick and apply pieces from P.diff to build
54 ... commits on topicB branch.
55
56 "topicB"
57 o---o---o---o---o
58 /
59 /o---o---o
60 |/ "topicA"
61 o---o"master"
Junio C Hamanoa77a5132007-06-08 16:13:4462 \ "topic"
Junio C Hamano63636e52006-02-12 13:31:3963 o---o---o---o---o---o
64
65After I am done, I'd try a pretend-merge between "topicA" and
66"topicB" in order to make sure I have not missed anything:
67
68 $ git pull . topicA ;# merge it into current "topicB"
69 $ git diff topic
70 "topicB"
71 o---o---o---o---o---* (pretend merge)
72 / /
73 /o---o---o----------'
74 |/ "topicA"
75 o---o"master"
Junio C Hamanoa77a5132007-06-08 16:13:4476 \ "topic"
Junio C Hamano63636e52006-02-12 13:31:3977 o---o---o---o---o---o
78
79The last diff better not to show anything other than cleanups
80for crufts. Then I can finally clean things up:
81
82 $ git branch -D topic
83 $ git reset --hard HEAD^ ;# nuke pretend merge
84
85 "topicB"
86 o---o---o---o---o
Junio C Hamanoa77a5132007-06-08 16:13:4487 /
Junio C Hamano63636e52006-02-12 13:31:3988 /o---o---o
89 |/ "topicA"
90 o---o"master"