Chris G.
Chris G.

Reputation: 25974

git rebase -i: I only want the last commit

I have been working on a branch:

       C1--D1--E1 branch
      /
 A--B--C--D--E--F master

On branch using "git rebase -i master" in a small test repo, I am able to get to here:

 A--B--C--D--E--F--E1 master

The problem is, that when there is an merge conflict git wants me to resolve each of the commits one by one from branch. I have been doing a lot of trial and error and therefore, I have a lot of commits - I just want to merge the working tree on to master without each of the commits.

If I do normal merge I get all the commits.

How would you do this?

Upvotes: 11

Views: 12394

Answers (3)

William Pursell
William Pursell

Reputation: 212288

Don't bother with the porcelain--just use git-commit-tree directly.

Use git commit-tree to create a new commit using the tree object of the tip of branch with the tip of master as its only parent. Then use git-branch to move the tip of master to the new commit.

$ git log --graph --pretty=oneline master branch
* 50f8c9d10b91b0e2dcb655b3055f78d5a0db8d07 (HEAD -> branch) E1
* b18725930d50d3849c44c0633745ee90426b5bc9 D1
* 42b9e39e55b199c16ae03b48ec1764e5925b8fdc C1
| * 90c0e72e5cea1cd679593d5e80809c9e93d8f546 (master) F
| * b3ab028cf298b31e31f428627f44c4ca62975be7 E
| * 635111478b11136848f548ee816c4bc3fa44a7a0 D
| * 25f8345a86888239e26a0a0e8152272caefcc56f C
|/  
* 429419a9f5ae7252e746d3065cefd1d4e2f3f3db B
* 655bf2661aef31c2fdcf35716018d15450f8aed9 A
$ echo 'E1' | git commit-tree -p master branch^{tree}
55b438965a28faadf6fc9997c21221cf5e558986
$ g branch -f master 55b4389
$ git log --graph --pretty=oneline master
* 55b438965a28faadf6fc9997c21221cf5e558986 (master) E1
* 90c0e72e5cea1cd679593d5e80809c9e93d8f546 F
* b3ab028cf298b31e31f428627f44c4ca62975be7 E
* 635111478b11136848f548ee816c4bc3fa44a7a0 D
* 25f8345a86888239e26a0a0e8152272caefcc56f C
* 429419a9f5ae7252e746d3065cefd1d4e2f3f3db B
* 655bf2661aef31c2fdcf35716018d15450f8aed9 A

Here, the two commits 50f8c9 and 55b4389 share the same tree object, which you can verify by examination:

$ git cat-file -p 50f8c9^{tree}
100644 blob f70f10e4db19068f79bc43844b49f3eece45c4e8    A
100644 blob 223b7836fb19fdf64ba2d3cd6173c6a283141f78    B
100644 blob e2cf5e790565bc0bf428eb2709e0bdf08cf9ca3e    C1
100644 blob 1151dc72d703d7d833943e1a1d44deddf3cdc338    D1
100644 blob b19a14e48ef3529034b8d2e070227469328da8cb    E1
$ git cat-file -p 55b4389^{tree}
100644 blob f70f10e4db19068f79bc43844b49f3eece45c4e8    A
100644 blob 223b7836fb19fdf64ba2d3cd6173c6a283141f78    B
100644 blob e2cf5e790565bc0bf428eb2709e0bdf08cf9ca3e    C1
100644 blob 1151dc72d703d7d833943e1a1d44deddf3cdc338    D1
100644 blob b19a14e48ef3529034b8d2e070227469328da8cb    E1

(The above is perhaps somewhat confused by the fact that I've used commit messages consisting of nothing but strings like "D1", and those same strings are also the names of files added by each commit.)

Upvotes: 0

mockinterface
mockinterface

Reputation: 14860

The main problem that you are facing is that on one hand you want to get rid of the history by melding everything into one commit, and on the other you want to avoid subsequent conflicts when you re-merge that branch. That is not possible in the general case. Thus when you reach the following state:

           C1--D1--E1 branch
          /
A--B--C--D--E--F--E1’ master

The whole of E1’ is at odds with the lineage of branch, and merge conflicts will ensue. It also looks to me that it is simpler to reach the exact state above by:

master $ git merge –squash branch
master $ git commit -m "E1’"

So what you can do? If you are willing to do away with the history of branch you can rebase everything into a single commit on the branch branch itself,

branch $ git rebase –i

creating this:

           E1’ branch
          /
A--B--C--D--E--F  master

Then merge the result into master,

master $ git merge branch

           E1’--o    branch
          /      \
A--B--C--D--E--F--M  master

Now if you continue the development on the branch – there should be no master merge conflicts that relate to the E1’ commit again.

Upvotes: 0

gran_profaci
gran_profaci

Reputation: 8461

To get only one commit, this is what you do :

Currently, your branch has 3 different commits. So, move it to a different branch : Say your branch is called testBranch

git branch newBranch
git reset --hard HEAD~3 (Or as many commits as you have)
git cherry-pick newBranch

Refer this answer for more info : Git - only push up the most recent commit to github

If you now do a git log on 'testBranch', you will find that you have only the last commit (E1). You can simply merge it with master using whatever command you want. I hope this helps.

Upvotes: 1

Related Questions