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