Skip to content

Instantly share code, notes, and snippets.

@nicholastmosher
Created July 3, 2019 02:43
Show Gist options
  • Select an option

  • Save nicholastmosher/d815ba56fd5da72781fff4cd0631fab9 to your computer and use it in GitHub Desktop.

Select an option

Save nicholastmosher/d815ba56fd5da72781fff4cd0631fab9 to your computer and use it in GitHub Desktop.

Git model:

Here's a simple way to think of git as a data structure rather than a magic box (not using any particular syntax):

history: Map<Hash, Commit>
Commit {
  changes: Diff,
  previous: Hash,
}
branches: Map<String, Hash>

Notice that it's pretty much a hashmap and a linked list put together. Each commit knows the changes that it applies and the hash of the commit that came before it. The history hashmap lets you look up any commit (and therefore, the entire "chain" of it's predecessors in the linked list). The branches are just a way to assign names to hashes.

Git process:

Suppose you're starting to work on a new feature, FEATURE-0001. You make a new branch off of master and start working. Your history will probably look something like this:

Note: To make a graph like this, I use an aliased command glgg (git log graph), defined like this: alias glgg="git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all"

* 8441e8b - (60 seconds ago) FEATURE-0001: Add tests for edge cases - Nick Mosher (HEAD -> FEATURE-0001)
* cb7ff76 - (67 seconds ago) FEATURE-0001: Fix some edge cases - Nick Mosher
* d790b4d - (75 seconds ago) FEATURE-0001: Begin adding tests - Nick Mosher
* 6ebc387 - (82 seconds ago) FEATURE-0001: Start implementation - Nick Mosher
* 2a7545d - (3 days ago) Merge pull request #5 from nmosher/SBGDATA-18205 - Nick Mosher (master)

When you finish your feature, you go to merge everything into master, only to discover that somebody else merged their work first, meaning your work will have a merge conflict. History now looks something like this:

*   00fee6b - (4 seconds ago) Merge branch 'FEATURE-0002' - Nick Mosher (HEAD -> master)
|\
| * 220a42c - (71 seconds ago) FEATURE-0002: Add tests for edge cases - Nick Mosher (FEATURE-0002)
| * 975a800 - (79 seconds ago) FEATURE-0002: Fix some edge cases - Nick Mosher
| * b17a988 - (87 seconds ago) FEATURE-0002: Begin adding tests - Nick Mosher
| * e2bfffa - (2 minutes ago) FEATURE-0002: Start implementation - Nick Mosher
|/
| * 8441e8b - (4 minutes ago) FEATURE-0001: Add tests for edge cases - Nick Mosher (FEATURE-0001)
| * cb7ff76 - (5 minutes ago) FEATURE-0001: Fix some edge cases - Nick Mosher
| * d790b4d - (5 minutes ago) FEATURE-0001: Begin adding tests - Nick Mosher
| * 6ebc387 - (5 minutes ago) FEATURE-0001: Start implementation - Nick Mosher
|/
*   2a7545d - (3 days ago) Merge pull request #5 from nmosher/SBGDATA-18205 - Nick Mosher

When looking at a graph like this, I like to think of every |/ as a "branch base", and every |\ as a "branch merge". The problem in this example is that the base of your FEATURE-0001 branch does not point to the current master (it points to where master was when you started). To fix this, we have to "rebase", i.e. we need to move the branch base up to the current commit where master is.

When you rebase, make sure you have your feature branch checked out. Then, the name of the branch you give to the rebase command will be the new "branch base", in this case that will be master.

git checkout FEATURE-0001
git rebase master

At this point, you may have to solve some merge conflicts if there are any. Be sure to resolve the conflicts, then add each file using git add, then use git rebase --continue. Repeat this process until all merge conflicts are resolved.

Your history after this will look like this:

* 491bfbd - (1 second ago) FEATURE-0001: Add tests for edge cases - Nick Mosher (HEAD -> FEATURE-0001)
* b11614c - (10 seconds ago) FEATURE-0001: Fix some edge cases - Nick Mosher
* dcc18a1 - (37 seconds ago) FEATURE-0001: Begin adding tests - Nick Mosher
* 865fb04 - (44 seconds ago) FEATURE-0001: Start implementation - Nick Mosher
*   00fee6b - (12 minutes ago) Merge branch 'FEATURE-0002' - Nick Mosher (master)
|\
| * 220a42c - (13 minutes ago) FEATURE-0002: Add tests for edge cases - Nick Mosher (FEATURE-0002)
| * 975a800 - (14 minutes ago) FEATURE-0002: Fix some edge cases - Nick Mosher
| * b17a988 - (14 minutes ago) FEATURE-0002: Begin adding tests - Nick Mosher
| * e2bfffa - (14 minutes ago) FEATURE-0002: Start implementation - Nick Mosher
|/
*   2a7545d - (3 days ago) Merge pull request #5 from nmosher/SBGDATA-18205 - Nick Mosher

Now we're back to having a "healthy" branch. In my mind, a branch is healthy when all of the commits are stacked in a straight line right on top of master. It also means that merging your branch into master will not cause any merge conflicts.

Once your feature is done, we can merge the branch like usual, and it will look like this:

*   a6cdd02 - (4 seconds ago) Merge branch 'FEATURE-0001' - Nick Mosher (HEAD -> master)
|\
| * 491bfbd - (4 minutes ago) FEATURE-0001: Add tests for edge cases - Nick Mosher (FEATURE-0001)
| * b11614c - (5 minutes ago) FEATURE-0001: Fix some edge cases - Nick Mosher
| * dcc18a1 - (5 minutes ago) FEATURE-0001: Begin adding tests - Nick Mosher
| * 865fb04 - (5 minutes ago) FEATURE-0001: Start implementation - Nick Mosher
|/
*   00fee6b - (17 minutes ago) Merge branch 'FEATURE-0002' - Nick Mosher
|\
| * 220a42c - (18 minutes ago) FEATURE-0002: Add tests for edge cases - Nick Mosher (FEATURE-0002)
| * 975a800 - (18 minutes ago) FEATURE-0002: Fix some edge cases - Nick Mosher
| * b17a988 - (18 minutes ago) FEATURE-0002: Begin adding tests - Nick Mosher
| * e2bfffa - (18 minutes ago) FEATURE-0002: Start implementation - Nick Mosher
|/
*   2a7545d - (3 days ago) Merge pull request #5 from nmosher/SBGDATA-18205 - Nick Mosher
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment