3

I would like to take a git history that contains branches with merge commits, and turn it into a single linear history without squashing all the commits from the branch into a single commit.

That is, starting from the following:

* d667df5 (HEAD -> master) Modify merged file
*   233e181 Merge branch 'featurebranch'
|\
| * bca198d (featurebranch) Modify the second file
| * fdc4e08 Add a different file
* | 5e0c25f Modify file yet again
* | 2426135 Modify file again
* | eb56b32 Modify file
|/
* c94a83e Add a file
* bfbfaaa Initial commit

... I would like a single line as follows:

* d667df5 (HEAD -> master) Modify merged file
* bca198d Modify the second file
* fdc4e08 Add a different file
* 5e0c25f Modify file yet again
* 2426135 Modify file again
* eb56b32 Modify file
* c94a83e Add a file
* bfbfaaa Initial commit

The reason I want this is because I am working in a feature branch with another developer. When pulling my changes he has repeatedly used git pull (i.e. creating merge commits) rather than rebasing. I want the history of this feature branch to be linear before merging it into master.

NB I am aware the commit IDs will likely be different in the result. I am also aware of all the usual consequences of rewriting history.

Update: Not a duplicate of this question since I want to preserve the individual commits in the branch rather than squash them into one.

Neil Bartlett
  • 23,743
  • 4
  • 44
  • 77

1 Answers1

4

I guess you want to make a rebase. Be sure to not have any changes in working dir. The global idea I like to do is to work on a new branch to reorganize the history, then make this branch the master one.

git checkout -b workingBranch featurebranch // create a new branch and checkout to featurebranch
git rebase 5e0c25f // This create your linear history, instead of merge. You may have to resolve commit for each commits of featurebranch
git checkout master
git reset --hard workingBranch // You will lose the commit d667df5 (HEAD -> master) Modify merged file. If it is not wanted, cherry-pick or rebase again
git branch -D workingBranch

I hope it helps.

Flows
  • 3,675
  • 3
  • 28
  • 52
  • This is the easy way, using `git rebase` to copy commits en masse. The one disadvantage is that you get the order that `git rebase` chooses when you might prefer some other order for the various commits. To choose your own order, do the rebase the "hard way", by creating the new branch as shown here, then cherry-picking each commit one at a time. (Note: you can `git checkout -b workingBranch featurebranch` to create the new name at the correct commit initially.) – torek Mar 16 '18 at 15:04
  • If I get right your point, I think an interactive rebase will allow you to choose the order you want and solve the case you noticed (I guess). – Flows Mar 16 '18 at 15:17
  • 1
    Yes, interactive rebase will allow you to rearrange the commits into the order you like. I prefer manually cherry-picking because I often want to inspect each commit as I go, rather than having a big list of `pick` commands in one window and having to figure out which hash is which and then fire off the entire sequence of cherry-picks all at once with no steering control any more. But others might prefer that. :-) – torek Mar 16 '18 at 15:21
  • Thanks for your explanation, it is always interesting to have differents points of view. – Flows Mar 16 '18 at 16:39