Documentation / howto / separating-topic-branches.txton commit Merge branch 'nd/git-dir-pointing-at-gitfile' into maint (f8aeacf)
   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"