Reputation: 14896
This gives a good explanation of squashing multiple commits:
http://git-scm.com/book/en/v2/Git-Branching-Rebasing
but it does not work for commits that have already been pushed. How do I squash the most recent few commits both in my local and remote repos?
When I do git rebase -i origin/master~4 master
, keep the first one as pick
, set the other three as squash
, and then exit (via c-x c-c in emacs), I get:
$ git rebase -i origin/master~4 master
# Not currently on any branch.
nothing to commit (working directory clean)
Could not apply 2f40e2c... Revert "issue 4427: bpf device permission change option added"
$ git rebase -i origin/master~4 master
Interactive rebase already started
where 2f40 is the pick
commit. And now none of the 4 commits appear in git log
. I expected my editor to be restarted so that I could enter a commit message. What am I doing wrong?
Upvotes: 882
Views: 692210
Reputation: 785
For whom might be interested, this is how it looks like when you squash commits in GitHub PR.
After:
Edit 1: Not that this view of PR page. If you mentioned an issue number in your commit message of your PR it will be automatically shown in github issue page. And in github issue page old commits and new (squashed/changed) commits will still be shown.
Upvotes: 3
Reputation: 2457
A lot of problems can be avoided by only creating a branch
to work on & not working on master
:
git checkout -b mybranch
The following works for remote
commits already pushed & a mixture of remote
pushed commits / local
only commits:
# example merging 4 commits
git checkout mybranch
git rebase -i mybranch~4 mybranch
# at the interactive screen
# choose fixup for commit: 2 / 3 / 4
git push -u origin +mybranch
Upvotes: 40
Reputation: 83
Many of the proposed solutions require doing a git push --force
at the end. In my case, the git repository was configured to disallow git push --force
, so I was stuck.
Here's how I went about squashing my commits on the feature-branch
:
git switch main
git switch -c feature-branch-2
git cherry-pick -n <hash>
git commit -m "New message"
git push origin -u feature-branch-2
git branch -D feature-branch
If you have the necessary permissions, you can also delete the old remote branch. Otherwise, you can ask someone with the appropriate permissions to do it, or simply wait for it to become stale.
Upvotes: 1
Reputation: 2487
MODEL
git cherry -v <ORIGINAL_BRANCH> <YOUR_BRANCH>
EXAMPLE
git cherry -v main some_branch_name
[Ref(s).: https://stackoverflow.com/a/24668421/3223785 ]
If there is more than one commit in the created branch, perform a rebase to centralize everything in just one commit.
TIP: This process is important for organizing and ensuring that all changes made in one branch can be brought over to another branch in a cherry pick process if this is the scenario.
The rebase is basically a "merge" of commits.
MODEL
git rebase -i origin/<YOUR_BRANCH>~<NUMBER_COMMITS_TO_REBASE> <YOUR_BRANCH>
EXAMPLE
git rebase -i origin/some_branch_name~2 some_branch_name
NOTE: The <NUMBER_COMMITS_TO_REBASE> means the number of commits you are going to merge (rebase) - that is, the number of commits displayed by the "List all specifc branch commits" command - and -i
means interactive mode.
A text editor will open. Keep only the commits (hash) shown by the "List all branch commit..." command. Keep the oldest commit (it will appear first) as "pick" and the others in sequence change to "squash". This configuration file after being saved will be executed as a batch by git.
MODEL
git push origin +<YOUR_BRANCH>
EXAMPLE
git push origin +some_branch_name
IMPORTANT: To force a push TO ONLY ONE BRANCH (<YOUR_BRANCH>), use a +
in front of it to push.
[Ref(s).: https://stackoverflow.com/a/5668050/3223785 ]
Upvotes: 0
Reputation: 74272
Squash commits locally with:
git rebase -i origin/master~4 master
where ~4
means the last 4 commits.
This will open your default editor. Here, replace pick
in the second, third, and fourth lines (since you are interested in the last 4 commits) with squash
. The first line (which corresponds to the newest commit) should be left with pick
. Save this file.
Afterwards, your editor will open again, showing the messages of each commit. Comment the ones you are not interested in (in other words, leave the commit message that will correspond to this squashing uncommented). Save the file and close it.
You will than need to push again with the -f flag.
and then force push with :
git push origin +master
--force
and +
From the documentation of git push
:
Note that
--force
applies to all the refs that are pushed, hence using it withpush.default
set tomatching
or with multiple push destinations configured withremote.*.push
may overwrite refs other than the current branch (including local refs that are strictly behind their remote counterpart). To force a push to only one branch, use a+
in front of the refspec to push (e.ggit push origin +master
to force a push to themaster
branch).
Upvotes: 1191
Reputation: 131
Sqush Changes in remote
git reset --soft master
git add .
git commit -m "this is the final commit message"
git push RemoteBranch --force
Upvotes: 13
Reputation: 2630
In my case requirement was to squash all the feature branch commits into one, to have a clean commit history. Utilized the GitHub UI to do so.
Problem:
Requirement:
Steps followed:
Now the featureBranchLatest will have a single commit of all the changes needed in a single commit, along with the latest changes from the master. Delete the old branch featureBranch if not required for reference.
Upvotes: 1
Reputation: 1445
Minor difference to accepted answer, but I was having a lot of difficulty squashing and finally got it.
$ git rebase -i HEAD~4
Push to the remote using:
$ git push origin branch-name --force
Upvotes: 133
Reputation: 659
1) git rebase -i HEAD~4
To elaborate: It works on the current branch; the HEAD~4 means squashing the latest four commits; interactive mode (-i)
2) At this point, the editor opened, with the list of commits, to change the second and following commits, replacing pick with squash then save it.
output: Successfully rebased and updated refs/heads/branch-name.
3) git push origin refs/heads/branch-name --force
output:
remote:
remote: To create a merge request for branch-name, visit:
remote: http://xxx/sc/server/merge_requests/new?merge_request%5Bsource_branch%5D=sss
remote:To ip:sc/server.git
+ 84b4b60...5045693 branch-name -> branch-name (forced update)
Upvotes: 17
Reputation: 4333
When you are working with a Gitlab or Github you can run in trouble in this way. You squash your commits with one of the above method. My preferite one is:
git rebase -i HEAD~4
or
git rebase -i origin/master
select squash or fixup for yours commit. At this point you would check with git status. And the message could be:
On branch ABC-1916-remote
Your branch and 'origin/ABC-1916' have diverged,
and have 1 and 7 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
And you can be tempted to pull it. DO NOT DO THAT or you will be in the same situation as before.
Instead push to your origin with:
git push origin +ABC-1916-remote:ABC-1916
The + allow to force push only to one branch.
Upvotes: 7
Reputation: 88
For squashing two commits, one of which was already pushed, on a single branch the following worked:
git rebase -i HEAD~2
[ pick older-commit ]
[ squash newest-commit ]
git push --force
By default, this will include the commit message of the newest commit as a comment on the older commit.
Upvotes: 7
Reputation: 591
git rebase -i master
you will get the editor vm open and msgs something like this
Pick 2994283490 commit msg1
f 7994283490 commit msg2
f 4654283490 commit msg3
f 5694283490 commit msg4
#Some message
#
#some more
Here I have changed pick for all the other commits to "f" (Stands for fixup).
git push -f origin feature/feature-branch-name-xyz
this will fixup all the commits to one commit and will remove all the other commits . I did this and it helped me.
Upvotes: 39
Reputation: 7282
On a branch I was able to do it like this (for the last 4 commits)
git checkout my_branch
git reset --soft HEAD~4
git commit
git push --force origin my_branch
Upvotes: 316