Based on the previous suggestions, this is the solution I've come up with:
Solution 1 with cherry-pick
Just commit the single change at the branch itself:
git add --patch <files> # record every change to move to master
git commit
Move to master, and cherry-pick
git stash
git checkout master
git cherry-pick <commitid>
Back in the branch, it can be rebased.
git checkout <branch>
git rebase master
For every duplicate commit, you will be prompted to type:
git rebase --skip
The duplicate commits are filtered out of the patch-set in the branch, and the history is clean. The final git merge
can still be fast-forward after-all.
Solution 2, without having to commit in the branch first
First extract everything to move to master:
git add --patch <files> # record every change to move to master
Then switch to master to commit:
git stash --keep-index # clear the working copy only
git checkout master -m # merge the index.
git commit
And back in the branch, it can be directly rebased to the tip of master:
git checkout <branchname>
git rebase master # move to branch start to the tip of master.
git stash apply # restore working copy, auto merges the changes
Solution 3, make a clone of the current master branch
In case you don't mind having multiple working copies (I always did this with SVN actually), there is a third solution:
mkdir ../newrepos
cd ../newrepos
git init
git remote add origin /path/to/your/repository
git fetch master:remotes/origin/master # fetch remote master to local remotes/origin/master
git checkout -t origin/master # make new "master" branch, link to remote, checkout.
git commit
git push origin master # inject the change in the original repository.
The clone setup is done manually here because git clone
always clones the currently active branch.
For more complex situations, there is always an extra safe guard with git diff > to-master.patch
and git apply to-master.patch
. This allows you more freedom to reset everything, and try over until you get things right.
In this situation, we're dealing with a one-line fix in a file which exists in both branches. This would not give any merge conflicts, and allows some shortcuts like checkout -m
.