Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to rewrite a branch's history without losing merge info along the way?

Tags:

git

We have a master branch into which we've merged about 10 feature branches, one at a time.

So the recent history looks like this:

merged feat/10 (HEAD of master)
merged feat/9
merged feat/8
merged feat/7
merged feat/6
merged feat/5
...

Now we found out that feat/7 was bad and we want to take it out of master. Reverting that merge commit isn't enough because we don't want that broken commit to exist in our history at all. We can't really use interactive rebase because that will flatten out the history to make it look as if it was all done on a single branch, and we want to preserve all that good merge history.

Is there a way to zap out a particular merge commit from a branch's history?

I'll note that the real history is much more complex than what you see in the example above, so manually re-doing all the merges since feat/7 wouldn't be a good option.

Edit

To clarify for those who vote to close this as a dup: this isn't the FAQ about how to take out a commit with rebase, which of course has been answered many times. The question here is about taking out a commit without flattening the merge history.

like image 218
Assaf Lavie Avatar asked Aug 06 '12 08:08

Assaf Lavie


People also ask

Does git merge preserve history?

In the Conceptual Overview section, we saw how a feature branch can incorporate upstream changes from main using either git merge or git rebase . Merging is a safe option that preserves the entire history of your repository, while rebasing creates a linear history by moving your feature branch onto the tip of main .

How do I rewrite history in github?

There are many ways to rewrite history with git. Use git commit --amend to change your latest log message. Use git commit --amend to make modifications to the most recent commit. Use git rebase to combine commits and modify history of a branch.

Does git squash rewrite history?

No history is rewritten. From the high-level commands, only git rebase and git commit --amend perform history rewrites.

Does rebase rewrite history?

Interactive rebase is one of those tools that "rewrite" Git history – and you shouldn't do this on commits that have already been shared with others. With this little warning message out of the way, let's look at some practical examples!


2 Answers

If your history currently looks like that and you didnt delete the branches yet you can simply git reset --hard HEAD~4 this will reset your code back to state before you merged in 7 then you can simply git merge the good ones back in. This is the simplest way I can think of off my head.

EDIT : You can use -p switch on rebase to preserve merges but using this switch with -i might have consequances. Check man git-rebase page and see the BUGS part to see current bugs.

EDIT2 : I don't take any responsibility if you don't take proper precautions before using this command. Don't use it before reading the manpage too.

like image 165
Learath2 Avatar answered Oct 12 '22 23:10

Learath2


You can use git filter-branch --parent-filter to rewrite the feat/8 commit so that its parent points to the feat/6 commit. Leaving the parents of all other commits (9-10) as they are, which should preserve merge commits in history as they were.

Only problem with this is what will happen to conflicts that result in the removed code changed ... there is no real way of knowing, and it might be the culprit.

like image 28
Evgeny Avatar answered Oct 13 '22 00:10

Evgeny