Monday, December 30, 2013

My Git bits and patterns

Based on the excellent guide by Sam Livingston-Gray: http://think-like-a-git.net

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 --hard
or
$ 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


No comments:

Post a Comment