Merge branch 'maint'
[git/git.git] / Documentation / howto / separating-topic-branches.txt
1 From: Junio C Hamano <junkio@cox.net>
2 Subject: Separating topic branches
3 Abstract: In this article, JC describes how to separate topic branches.
4
5 This text was originally a footnote to a discussion about the
6 behaviour of the git diff commands.
7
8 Often I find myself doing that [running diff against something other
9 than HEAD] while rewriting messy development history. For example, I
10 start doing some work without knowing exactly where it leads, and end
11 up with a history like this:
12
13 "master"
14 o---o
15 \ "topic"
16 o---o---o---o---o---o
17
18 At this point, "topic" contains something I know I want, but it
19 contains two concepts that turned out to be completely independent.
20 And often, one topic component is larger than the other. It may
21 contain more than two topics.
22
23 In 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
25 picking pieces from it to get logically self-contained units, and
26 start 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.
32
33 o---o---o
34 / "topicA"
35 o---o"master"
36 \ "topic"
37 o---o---o---o---o---o
38
39 Before doing each commit on "topicA" HEAD, I run "diff HEAD"
40 before update-index the affected paths, or "diff --cached HEAD"
41 after. Also I would run "diff --cached master" to make sure
42 that the changes are only the ones related to "topicA". Usually
43 I do this for smaller topics first.
44
45 After that, I'd do the remainder of the original "topic", but
46 for that, I do not start from the patchfile I extracted by
47 comparing "master" and "topic" I used initially. Still on
48 "topicA", I extract "diff topic", and use it to rebuild the
49 other 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"
62 \ "topic"
63 o---o---o---o---o---o
64
65 After 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"
76 \ "topic"
77 o---o---o---o---o---o
78
79 The last diff better not to show anything other than cleanups
80 for 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
87 /
88 /o---o---o
89 |/ "topicA"
90 o---o"master"