3

I've been working on a feature branch for a few weeks, and have a history of about 80 commits involving work across many sections of our project. For small features I would just rebase, squash the commits into one succinct commit, merge it to develop, and push it. But here I've accumulated a long history with commits touching many different parts.

I'd like to split them into smaller commits, i.e. "Finished portion A of Feature F" "Finished portion B".. etc, but the work was not linear and each piece was built up at the same time.

I could squash them all into one commit and push it, but I'd lose all the history and it might make debugging in the future a pain because it's such a large change.

I'm new to using git in a professional environment so I'm unsure of the best practices. What would your approach be to this situation?

René Link
  • 48,224
  • 13
  • 108
  • 140
Seventh Helix
  • 727
  • 4
  • 9
  • 18

1 Answers1

5

The general aproach is

  1. Split the mixed feature commits
  2. Reorder the commits

I assume that your repository looks like this

o--------o----------o----------o
A        B          C          D

and that your feature changes are mixed and distributed

- feature 1 changes are in A,B,C
- feature 2 changes are in A,C,D
- feature 3 changes are in B,C,D

Split the commits

If you want to bring the changes for every feature in line you must first split the commits.

$ git rebase -i HEAD~3

which will open an editor

pick A ...
pick B ...
pick C ...
pick D ...

Since you need to edit every commit change it to

edit A ...
edit B ...
edit C ...
edit D ...

Save and quit the editor and git will start to rebase. Git will rebase A and pause to let you do the edit. Now you can reset commit A and make new commits in order to reflect every feature change.

$ git reset HEAD~
$ git add ... # only files of feature A
$ git commit -m 'Feature A'
$ git add ... # only files of feature B
$ git commit -m 'Feature B'
$ git add ... # only files of feature C
$ git commit -m 'Feature B'
$ git rebase --continue

Git continues and you must repeat the above example again and again until all commits are splitted up. Your repository than looks like

o---o---o---o---o---o---o---o---o
E   F   G   H   I   J   K   L   M

See also Break a previous commit into multiple commits

Reorder the commits

For now you have all changes to one feature in a single commit. But they are not in a linar order:

  • feature 1 changes are in E, G, I
  • feature 2 changes are in F, J, L
  • feature 3 changes are in H, K, M

Now you can do another rebase -i and reorder the commits.

pick E
pick G
pick I
pick F
pick J
pick L
pick H
pick K
pick M

Save and quit the rebase interactive editor and git will reorder the commits. It might be possible that you get merge conflicts that you must solve. The commits will be reordered and therefore they might conflict with the prevoious commit now.

Hopefully git rebase completes without any conflict and you will end up with this repository

 o---o---o---o---o---o---o---o---o
 N   O   P   Q   R   S   T   U   V

|         | |         | |         |
+---------+ +---------+ +---------+
 feature 1   feature 2   feature 3
Community
  • 1
  • 1
René Link
  • 48,224
  • 13
  • 108
  • 140