Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collapse a branch down to one commit

Tags:

git

github

Basically I have been working on a feature but when I push the feature back to the main repo for code review they like the entire feature to be pushed as one commit. I normally use git rebase -i for this and set everything except for the first commit to squash and the first to edit. I then paste in the latest files in every time there is a conflict.

I would rather not have to paste various files in during conflicts. I would like to be able to keep the latest files and delete the history of how they came to be in an easier command basically.

EDIT:

I am looking for a Git command equivalent to this bash script:

for file in `git diff --name-only master foo`
git checkout foo $file
like image 333
kporter Avatar asked Oct 25 '25 17:10

kporter


2 Answers

Use Squashed Merges

What you want is a squashed merge. This merges all your changes into the working tree, but it's up to you to make the actual commit. For example:

git checkout foo
git rebase -i master
git checkout master
git merge --squash foo
git commit -m 'Squashed commit.'

All your changes from the rebased branch will be made as a single commit, with a single commit message. As long as you resolved any conflicts with your rebase in the foo branch, the merge should generate no conflicts when you merge into master.

like image 135
Todd A. Jacobs Avatar answered Oct 27 '25 16:10

Todd A. Jacobs


If you git rebase -i '@{upstream}' (squashing as described) you may have genuine conflicts which need real resolutions. If you just copy paste over the changes then you may be undoing changes on the remote that have happened since you began feature development regressing functionality.

If you know that this is safe for an individual file then during the rebase you can always do git checkout --theirs $file to avoid having to copy paste, though this will replace the entire file which could replace hunks which where auto merged; in this case 'theirs' is the change set being applied, i.e. your changes.

If you are sure that this is always the case then you can set a merge strategy, for example git rebase -m -s merge-recursive -X theirs -i '@{upstream}'.

Note: This only works for interactive rebases in recent versions of Git.

To my mind a simpler approach is to do git rebase -i \ git merge-base HEAD '@{upstream}'\ (squashing as described) effectively rebasing the branch onto itself. The result will be no merge conflicts to resolve in this step as the changes are being applied in the same order they were created onto the same code. This would then be follow with a git rebase '@{upstream}' at which point you would resolve conflicts with the upstream in the normal way.

Even easier, assuming you can manage the files well, would be to git reset \ git merge-base HEAD '@{upstream}'\. At this point you simply add the files you changed to the stage and make a new commit which can be rebased as mentioned in the previous paragraph.

like image 36
Daniel Avatar answered Oct 27 '25 15:10

Daniel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!