0

I have a project where I work by branching from develop branch, doing some job in that feature branch, merging it back to develop. After this I delete feature branch.

Due to the need of cross merging, and such, my commit history is pretty ugly. But I still delete feature branches after merge, but my git keeps track of commits having different parents.

How do I make this tree linear, into one line? There is only one branch there, develop.

EDIT: This is not duplicate of merge vs rebase, as I want to update my tree post-factum, now there only is one branch.

enter image description here

Peter Wood
  • 23,859
  • 5
  • 60
  • 99
Dvole
  • 5,725
  • 10
  • 54
  • 87
  • Possible duplicate of [git workflow and rebase vs merge questions](http://stackoverflow.com/questions/457927/git-workflow-and-rebase-vs-merge-questions) – Andrew C Jan 15 '16 at 19:26
  • In that case - http://stackoverflow.com/questions/3026218/how-to-use-git-rebase-to-clean-up-a-convoluted-history – Andrew C Jan 15 '16 at 19:40
  • @Dvole your branches look great which software are you using to visualize the tree? – uday Jan 15 '16 at 19:51
  • 1
    What benifit does a pretty branch history give ? Merge with the squash flag to get what you want but you lose history which is arguably more valuable than a "pretty graph" – exussum Jan 16 '16 at 10:02
  • 1
    @udaY Atlassian Sourcetree – Dvole Jan 16 '16 at 10:48

2 Answers2

1

Let's consider the first blue node in the history where the ugly branching begins to be the start point. Let us call its hash S.

First, let's gather a list of the commits we would like to linearize:

git log --oneline --reverse --full-history --simplify-merges S..HEAD > commits

Now, let us throw away all that history and reset the branch back to S:

git reset --hard S

Finally, let us use git rebase --interactive to pick those commits into the branch:

# Null rebase with no commits:
git rebase -i HEAD

Now we are sitting in a text editor, with the buffer containing the word noop: we have initiated a blank rebase of nothing. Delete the noop line and in its place, read the commits file into the edit buffer. In front of each line, add the prefix p to pick that commit. Re-arrange the order as you like. Then save and quit. The interactive rebase script will happily oblige and cherry pick all the commits we added into the buffer.

You now have to deal with the interactive rebase workflow to resolve any conflicts arising from the order in which these are picked.

It could be that this is doable in one step, perhaps with git rebase -i S. I'm not sure how rebase deals with convoluted histories. The above approach makes it concrete; we tweak the git log options to extract the exact list of commits that we want, and if we are happy with what's in the commits file, we (ab)use interactive rebase to cherry pick it for us.

You should triple-check that commits contains what you want from the graph. When the dust settles, do a git diff <original-HEAD-SHA> to see what is different. Ideally there should be no difference at all, or only some trivial diffs based on doing some merge resolution slightly differently (e.g. order of declaration of variables in some function and such).

Kaz
  • 55,781
  • 9
  • 100
  • 149
0

@Kaz suggested to rebase everything interactively, but this gives huge pains with merges, and I have found a better way.

First do this:

git filter-branch --parent-filter 'cut -f 2,3 -d " "'

After it is done, do git push -f

This is thoroughly explained here: How do I trivially linearize my git history?

Community
  • 1
  • 1
Dvole
  • 5,725
  • 10
  • 54
  • 87