Page 32 - MSDN Magazine, June 2017
P. 32
The user named the branch feat_print_preview, based it on master and checked the Checkout branch checkbox in Team Explorer’s New Local Branch From pane. Checking the checkbox tells Git that you want the new branch to become the current branch (I’ll explain this in a moment). Behind the scenes, Git creates a new head file in the heads folder called feat_print_preview and places the SHA-1 value for com- mit object A3 into it. This now means that two files exist in the heads folder: master and feat_print_preview—both of which point to A3.
At Commit 04, Git is faced with a decision: Normally, it would update the SHA-1 value for the file reference in the heads fold- er—but now it’s got two file references in that folder, so which one should it update? That’s what HEAD does. HEAD (all uppercase) is a single file in the root of the .git folder that points to a “head” (all lowercase) file in the heads folder. (Note that “HEAD” is actually a file that’s always named HEAD, whereas “head” files have no par- ticular name.) The head file HEAD contains the commit ID that will be assigned as the parent ID for the next commit object. In a practical sense, HEAD marks Git’s current location on the DAG, and there can be many heads but there’s always only one HEAD.
Going back to Figure 8, Commit 01 shows that HEAD points to the head file called master, which, in turn, points to A1 (that is, the master head file contains the SHA-1 for commit object A1). At Commit 02, Git doesn’t need to do anything with the HEAD file because HEAD already points to the file master. Ditto for Commit 03. However, in the Create and Check-Out New Branch step, the user created a branch and checked out the files for the branch by marking the Checkout branch checkbox. In response, Git updates HEAD so that it points to the head file called feat_print_preview
rather than to master. (If the user hadn’t checked the Checkout branch checkbox, HEAD would continue to point to master.)
Armed with knowledge about HEAD, you now can see that Commit 04 no longer requires Git to make any decision: Git simply inspects the value of HEAD and sees that it points to the head file called feat_print_preview. It then knows that it must update the SHA-1 in the feat_print_preview head file so that it contains the commit ID for B1.
In the Checkout Branch step, the user accessed the Team Explorer branches pane, right-clicked the master branch and chose Checkout. In response, Git checks out the files for Commit A3 and updates the HEAD file so that it points to the head file called master.
At this point, it should be clear why branch operations in Git are so efficient and fast: Creating a new branch boils down to creating one text file (head) and updating another (HEAD). Switching branches involves updating only a single text file (HEAD) and then usually a small performance hit as files in the working directory are updated from the repo.
Notice that commit objects contain no branch information! In fact, branches are maintained by only the HEAD file and the various files in the heads folder that serve as references. Yet when developers using Git talk about being on a branch or they refer to a branch, they often are colloquially referring to the sequence of commit objects that originates with master or from a newly formed branch. The earlier Figure 2 shows what many developers would identify as three branches: A, B and C. Branch A follows the sequence A1 through A6. Branch activity at A4 produces two new branches: B1 and C1. So the sequence of commits that begins with B1 and continues to B3 can be referred to as Branch B while the se-
Commit 01
A1
master
(head) HEAD
Create and Checkout New Branch
A1 A2 A3
Commit 02
A1 A2
master
(head) HEAD
Commit 03
A1 A2 A3
quence from C1 to C2 can be referred to as Branch C.
The takeaway here is not to forget the formal definition of a Git branch: It’s sim- ply a pointer to a commit object. More- over, Git maintains branch pointers for all branches (called heads) and a single branch pointer for the current branch (called HEAD).
In my next article I’ll explore details about checking out and checking in files from and to the repo, and the role of index and how it constructs tree objects during each commit. I’ll also explore how Git optimizes storage and how merges and diffs work. n
Jonathan Waldman is a Microsoft Certified Professional who has worked with Microsoft tech- nologies since their inception and who specializes in software ergonomics. Waldman is a member of the Pluralsight technical team and he currently leads institutional and private-sector software- development projects. He can be reached at jonathan.waldman@live.com.
thanks to the following Microsoft technical experts for reviewing this article:
Kraig Brockschmidt and Ralph Squillace
Commit 04
master
(head) HEAD B1
feat_print_preview
(head) HEAD
A1 A2 A3
(head)
Checkout Previous Branch
A1 A2 A3
master
(head) HEAD (head) B1
feat_print_preview
(head)
master feat_print_preview master
(head) HEAD
Figure 8 Two Heads Are Better Than One: Git Maintains Various Files in Its Heads
Folder Along with a Single HEAD File
28 msdn magazine
DevOps