Reputation: 363
I am currently working on a project with multiple others. The problem is that we created a fork of an existed project and need to squash all our commits from after the forking process to a single commit for a pull-request on Bitbucket.
Is there any way (preferably using SourceTree, otherwise terminal) to squash already pushed commits to a single commit, such that the history within Bitbucket of all the commits are also only that one commit plus the commits which were already there before we forked the project?
Take as example just a simple project with a few files in only a master
branch.
Upvotes: 20
Views: 63947
Reputation: 3206
You can use this script for squash all commit of current branch and with final commit message.
#!/bin/sh
# brief: This script should be run from within your git repo. You need to have your feature branch
# checked out. This will squash all the commits on your feature branch (assuming you
# branched from master). Then you can just use the github PR UI to merge the PR in. You need to have
# feature branch checked out when you run this script (git checkout feature branch).
# usage: git-helper-squash-all-commits <final commit messsage ex: "reorganizing directory structure"
# example: git-helper-squash-all-commits "reorganizing directory structure"
set -ex
FINAL_COMMIT_MESSAGE=$1
BRANCH_YOU_BRANCHED_FROM=master
CURRENT_BRANCH=`git rev-parse --abbrev-ref HEAD`
COMMIT_HASH=`git merge-base HEAD $BRANCH_YOU_BRANCHED_FROM`
git reset --soft $COMMIT_HASH
git commit -am "$FINAL_COMMIT_MESSAGE"
git push origin $CURRENT_BRANCH --force
Upvotes: 4
Reputation: 363
Found a nice summary of the posted answers. This one is a bit more clear: squash pushed commits. It will require creating a second branch upon the creation of the fork. This second branch can have as many pushes to the remote server as needed.
Create a new personal branch that will be squashed.
# Start with the existing personal branch that contains all of your commits.
$ git checkout {ExistingBranchName}
# Create a new personal branch that will be squashed.
$ git checkout -b {BranchName}
Identify the first commit where your personal branch diverged from an existing CEF branch.
# Replace {BranchName} with your new branch name.
# Replace "master" with a different CEF branch as appropriate
# (e.g. "2272", "2171", etc).
$ git merge-base {BranchName} master
Start an interactive rebase using the commit hash returned from step 2.
$ git rebase --interactive {hash}
This will launch a text editor with a list of all commits in your personal branch. It should look something like this:
pick 59d2a23 Initial implementation
pick 752ae4c Add more features
pick cd302a3 Fix something
pick 5410de3 Fix something else
Change all but the first line to say squash
instead of pick
. The contents should now look like this:
pick 59d2a23 Initial implementation
squash 752ae4c Add more features
squash cd302a3 Fix something
squash 5410de3 Fix something else
Save the changes and close the file (Can be done by pressing esc
and type: :wq
.
A new file will now open containing the commit messages from all of the commits. Reword the commit message then save the changes and close the file.
Push the modifications to your personal remote repository.
# If the branch has already been pushed to the remote repository
# you will need to add the `--force` argument.
git push origin {BranchName}
# or git push origin {BranchName} --force
Upvotes: 16
Reputation: 466
There is a simpler way.
If you are absolutely certain that no one will ever use that specific branch you can do the following:
git reset --soft <hash>
git rebase -i
to move your local branch to the tip of master.Upvotes: 5
Reputation: 18834
Rebasing is easy to do with SourceTree, in sourcetree select the commit that you based your work on, then press the right mouse button.
Then a menu will popup, select "interactively rebase children of "
This will open a screen where we can select what to do with every commit. Since we want to squash every commit together, we click the top commit and select the button "Squash with previous" at the bottom of the screen. Sourcetree will update the top screen in response to the actions you did so you can see its doing what you want.
Before:
After:
Usually, you also want to change the message of the commit when you squash them together, double click on the message to change it. If you are done with the changes, press "ok" at the right bottom corner. Source Tree will now rebase the history for you.
Finished result:
Now you can force push your branch to your own fork of the other project and try to make another pull request.
Upvotes: 4
Reputation: 2296
git rebase
!Bitbucket use the Git software.
alex said it already in his post: Use the
git rebase -i ourbranchname
command!
Use these commands in the terminal, command prompt or in your cmd:
git rebase -i yourbranchname
pick
" to "fixup
" but one commit must have "pick
"!git push -f origin yourbranchname
Upvotes: 4
Reputation: 490617
...we created a fork of an existed project and need to squash all our commits from after the forking process to a single commit for a pull-request on Bitbucket
Note that you don't need a single commit for a pull request. A bunch of commits can constitute a pull request.
Is there any way (preferably using SourceTree, otherwise terminal) to squash already pushed commits to a single commit?
Yes, you can use an interactive rebase git rebase -i
.
You can then mark the commits you want to squash (follow the on-screen instructions that appear in your editor) and then write a new commit message when you have finished (use git rebase --continue
after each commit you have worked on).
If you have pushed them already, you will need to force push with the -f
option. Note that this is frowned upon, as anyone else that has pulled down these changes has to jump through hoops potentially to resync with the new history.
There may be a way to do it in SourceTree.
Upvotes: 2