1. Scout Pattern for testing a merge.
Switch to a branch to merge into:
$ git checkout feature_A
I---J---K feature_B
/
F---G---H feature_A
/
A---B---C---D---E master
Create and checkout a new branch:
$ git checkout -b test_merge
I---J---K feature_B
/
/ L test_merge
/ /
F---G---H feature_A
/
A---B---C---D---E master
Merge with the other branch:
$ git merge feature_B
I---J---K feature_B
/ \
/ L---M test_merge
/ /
F---G---H feature_A
/
A---B---C---D---E master
Resolve merge conflicts and test the merge.
If merge works, keep it and merge into the feature_A:
$ git checkout feature_A
$ git merge test_merge
If merge does not work, switch to feature_A (or "master") and delete the test_merge:
$ git checkout feature_A
$ git branch -D test_merge
To abort the merge:
$ git reset --hardor
$ git reset --hard feature_A
2. Relative references for testing a merge.
This is an extension of the Scout Pattern, with no extra step to create a checkpoint.
Switch to a branch to merge into:
$ git checkout feature_A
I---J---K feature_B
/
F---G---H feature_A
/
A---B---C---D---E master
Merge with the other branch:
$ git merge feature_B
I---J---K feature_B
/ \
F---G---H---L feature_A
/
A---B---C---D---E master
Resolve merge conflicts and test the merge.
If merge works, just keep the feature_A, and do nothing.
If merge does not work, hard reset to a prior checkpoint:
$ git reset --hard HEAD^
I---J---K feature_B
/
F---G---H feature_A
/
A---B---C---D---E master
Note: the relative checkpoint syntax HEAD^, HEAD^^, HEAD~3, etc.
To abort the merge:
$ git reset --hard
3. Undo a commit with missing info, misspelled messages, etc.
Move to prior checkpoint. This leaves the working tree as it was before "reset" (all local changes since HEAD^ are preserved):
$ git reset --soft HEAD^
Edit and commit files:
$ git commit -a -c ORIG_HEAD
All of the above commands are practical and I would use them in most situations. I have yet to see a case to use the following command.
4. Rebase allows to "replay" part of checkin history at a different base.
So, having the following tree of checkins:
I---J---K topic
/
F---G---H checkpoint
/
A---B---C---D---E master
To "move" all related checkins, the following command will reapply G, H, I, J, K one-by-one, in order, at the new base "master":
$ git rebase master topic
I'---J'---K' topic
/
F'---G'---H' checkpoint
/
A---B---C---D---E master
Note: Those changes at the "topic" branch that were previously applied to "master" in some prior merges, will not be replayed by rebase. Checkins that are not part of the "topic's" history will remain unchanged (C, D, and E).
To specify a subrange of checkins to rebase from the "topic" branch, add "--onto <base>" parameter followed by a range ("checkpoint" to "topic"):
$ git rebase --onto master checkpoint topic
F---G---H checkpoint
/
/ I'---J'---K' topic
/ /
A---B---C---D---E master