How to squash my git branch commits into the same branch without rebasing?
Asked Answered
K

3

12

I have a local branch, we're using git-flow with Pull Requests and I'm looking to squash a few commits after receiving PR feedback.

How can I squash all my commits (from PR's for example) into the same branch?

I imagine it would be something like:

git checkout master                    # For master
git pull                               # Get all branches up-to-date
git checkout feature1                  # Checkout the branch
git checkout -b feature1_squash        # Make a copy of the branch
git branch -D feature1                 # Delete original branch
git checkout master                    # (?) Branch off latest master for safety
git checkout -b feature1               # Make new (empty) original branch
git merge --squash feature1_squash     # Merge with squash into it
git push -f feature1                   # Push, force will be required

but I'm not sure.
With that many steps it also seems like a good case for using a function to tie it all together and just pass the branch name as a parameter. Of course automating it would mean making sure to handle errors, exceptions, edge cases, etc.

I don't want to use interactive rebase because it's a little tricky to get right for newbies that I train. I also don't want to have to know the number of commits, I just want to do all the ones that exist on this branch.

Karmakarmadharaya answered 4/12, 2015 at 13:5 Comment(2)
I don't understand exactly what you want. Do you have several branches with different commits on each and you want to put them all into one commit on one branch, thereby losing the development history?Assemble
I have 1 branch ('feature1') with several commits and I want there to be 1 commit.Karmakarmadharaya
T
7

The answer from VonC is almost there. but knowing that you want to go 3 commits back is tough.

instead you should use merge-base

git reset --soft $(git merge-base YOUR_BRANCH WHERE_YOU_BRANCHED_FROM)
git commit

and edit your message (or use git commit -m instead)

if your on that branch, you can use HEAD and assuming you branched from master your commands would be (using origin/master due to local master being potentially out of date)

git reset --soft $(git merge-base HEAD origin/master)
git commit

If you cant remember where you branched from, the place you are merging the PR back in to is likely correct

Tunic answered 9/12, 2015 at 20:33 Comment(1)
plus one for not needing to know the number of commitsKarmakarmadharaya
G
1

I think what youre suggesting is unconventional, and more tricky for newbies than using rebase -i to squash.

What is difficult about git rebase -i HEAD~N (with N being the number of commits to go back to for squashing)? You simply read the list, and squash down the commits as you need. The "Rewriting History" guide has more detail, and I think its perfectly suitable for a new user.

You could always make a demo branch for your trainees to practice on. Simply make 5-6 commits to a branch for demo purposes, and have the trainee squash the commits with interactive rebase, then make a PR to you to prove they can handle it on a live branch.

Gravesend answered 4/12, 2015 at 13:48 Comment(3)
Thanks. rebasing has been causing us problems. (too) long story. If my steps can be packaged into a function it would hide the complexity. We can do a demo branch but we will still end up with cases where Pull Request comments come in and we make a small change and we want to squash it.Karmakarmadharaya
I still believe that hiding the complexity (and also circumventing the tool's typical use cases, and using external tools to cause the same behavior) is a detriment to your trainees. I do believe that, as competent programmers, once they rebase a few times, it will become second nature. You could also use tools like gitosis (git-scm.com/book/en/v1/Git-on-the-Server-Gitosis) to controll access to various features, though its also its own layer of complexity. In any event, good luck, I hope theyre able to learn well!Gravesend
Forget gitosis, it's not maintained anymore. gitolite replaces it and it is maintained.Ecliptic
S
0

The alternative to an interactive rebase to squash commits (especially consecutive commits on a branch) is a git reset --soft.
See "Squash my last X commits together using Git"

git reset --soft HEAD~3 && 
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"

This is one of the "Practical uses of git reset --soft" I mentioned before.

Silvertongued answered 7/12, 2015 at 13:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.