Dizzam
Dizzam

Reputation: 33

How to join two early commits to one commit

For a repository like this:

init---A---A2---...---[D---B---merge]---...---master
                        \      /
                         C---B2

where B and B2 have conflict and was solved in merge commit.

now I want to join commit A and A2 to one commit A. And I tried

git rebase -i <commit id of init>

and change

pick xxxxxxx A
pick xxxxxxx A2
...

to

pick xxxxxxx A
squash xxxxxxx A2
...

but conflicts appeared when applying B2, and I have to deal with the conflicts manually just like what I have done in merge.

Actually, there are so many structures like or even more complex than in square brackets in the whole commit tree. So it's not realistic to deal with all the conflicts manually.

The problem is that when I use rebase, the whole commit tree will merged into one line and it will not deal with the conflict automatically by applying the commit merge.

So what can I do to join only the commits A and A2 but still remain all the commit structure after A2 unchanged so that the repository 'looks' the same after the operation?

To make some further explanation, in commit A there's some sensitive information added in a test file and it was removed in commit A2. So I can't publish this project if I can't remove these information permanently. So is there any alternative solution to this situation?

Upvotes: 0

Views: 210

Answers (2)

Marina Liu
Marina Liu

Reputation: 38106

You can also use use steps to join the two early commits together.

Assume the commit you want to join is on master branch, and the commit history as:

A---B---C---D---…---X  master

To join commit B and commit C together while keeping the commit history after commit C (commits from D to X), you can use below commands:

git checkout -b temp <commit id for A>
git merge <commit id for C> --squash
git commit -m 'join B and C together'

Now the commit history will be (commit M is the squash merged commit, join commit B and commit C together):

A---B---C---D---…---X  master
 \
  M  temp

Then you can rebase the following commits after commit C:

git rebase --onto temp <commit id for C> master
git push -f origin master
git branch -D temp

Now the commit history on master branch will be (commit M is the commit join commit B and commit C together):

A---M---D'---…---X'  master

Upvotes: 0

yarwest
yarwest

Reputation: 990

To join (or 'squash' as it's called) you need to interactively rebase. If the commits you want to alter are the first two, you can rebase from the root of the repo.

This would look a little something like:

git rebase -i --root
pick hash X
squash hash Y
pick hash Z

The -i means you will be doing it interactively. --root means starting from the root of the repo.

After that initial command you will see a list of commits with the top one being the first commit. To merge the first two commits you can simply keep the first one (with the pick keyword) and merge the previous one into it (using the squash keyword). You could also edit the first commit message by replacing pick with reword.

After you've done this, you should leave all the other commits be and confirm.

More information can be found here

Upvotes: 1

Related Questions