Last Friday at end of the day and I was attempting to push my changes to our team repo when I was hit with a ton of merge conflicts. I shut down my computer and went home, although thoughts of the merge haunted me over the weekend.
So when I got in today I sat with one of my coworkers, who is a git magician, and we did some trouble shooting. What I learned was that my git conception was completely wrong.
So what is git? As I understood it, it was a repository which stored ONLY FILE CHANGES tagged by a hash (a long string of numbers and letters. This makes it useful when you work, either alone, or with a team, to change documents or code. You have a clean audit trail of the list of changes. This, I think, is even more valuable than the ability to roll back changes.
On git there is a notion of a branch. I always thought that a branch was an organized list of commits. That branches did not know about each others commits and that branches were the fundamental unit of git.
I WAS WRONG
The commit is the fundamental unit of git – the change. Git could be conceived as a linked list. With each commit pointing to its parent. The hash of a commit, in fact, encodes the parent of the commit. The branch is just a pointer to a particular commit.
Since the basic unit in git is the commit, you have a lot of flexibility to re organize the commits either within a branch or between branches. When you rebase two branches in git, two lists of linked lists, git tries to preserve the timeline (the dates) of each commit.
My hairy git nightmare started with a rebase. The parent I was trying to rebase on two was missing my commit as well as three other commits and this caused git to think I needed to merge files since it detected changes in these 3 intermediary files. In order to fix this what I did was move the one commit I wanted to add on the parent branch and then move the branch name pointer to this new commit so this was now the head of the linked list. I did this via the cherry pick command.
It is good that we keep our commits small at my company, and that we keep commits on individual branches. It makes it easy to move around individual commits. But it also gives me a lot of confidence that even if I want to rebase (or re order ) a list of commits I can do this since each commit is its own atomic unit.