(window.webpackJsonp=window.webpackJsonp||[]).push([[1137],{1545:function(e,t,a){"use strict";a.r(t);var o=a(31),s=Object(o.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"internals"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#internals"}},[e._v("#")]),e._v(" Internals")]),e._v(" "),a("h2",{attrs:{id:"repo"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#repo"}},[e._v("#")]),e._v(" Repo")]),e._v(" "),a("p",[e._v("A "),a("code",[e._v("git repository")]),e._v(" is an on-disk data structure which stores metadata for a set of files and directories.")]),e._v(" "),a("p",[e._v("It lives in your project's "),a("code",[e._v(".git/")]),e._v(" folder. Every time you commit data to git, it gets stored here. Inversely, "),a("code",[e._v(".git/")]),e._v(" contains every single commit.")]),e._v(" "),a("p",[e._v("It's basic structure is like this:")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[e._v(".git/\n objects/\n refs/\n\n")])])]),a("h2",{attrs:{id:"objects"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#objects"}},[e._v("#")]),e._v(" Objects")]),e._v(" "),a("p",[a("code",[e._v("git")]),e._v(" is fundamentally a key-value store. When you add data to "),a("code",[e._v("git")]),e._v(", it builds an "),a("code",[e._v("object")]),e._v(" and uses the SHA-1 hash of the "),a("code",[e._v("object")]),e._v("'s contents as a key.")]),e._v(" "),a("p",[e._v("Therefore, any content in "),a("code",[e._v("git")]),e._v(" can be looked up by it's hash:")]),e._v(" "),a("p",[a("code",[e._v("git cat-file -p 4bb6f98")])]),e._v(" "),a("p",[e._v("There are 4 types of "),a("code",[e._v("Object")]),e._v(":")]),e._v(" "),a("ul",[a("li",[a("code",[e._v("blob")])]),e._v(" "),a("li",[a("code",[e._v("tree")])]),e._v(" "),a("li",[a("code",[e._v("commit")])]),e._v(" "),a("li",[a("code",[e._v("tag")])])]),e._v(" "),a("h2",{attrs:{id:"head-ref"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#head-ref"}},[e._v("#")]),e._v(" HEAD ref")]),e._v(" "),a("p",[a("code",[e._v("HEAD")]),e._v(" is a special "),a("code",[e._v("ref")]),e._v(". It always points to the current object.")]),e._v(" "),a("p",[e._v("You can see where it's currently pointing by checking the "),a("code",[e._v(".git/HEAD")]),e._v(" file.")]),e._v(" "),a("p",[e._v("Normally, "),a("code",[e._v("HEAD")]),e._v(" points to another "),a("code",[e._v("ref")]),e._v(":")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[e._v("$cat .git/HEAD\nref: refs/heads/mainline\n\n")])])]),a("p",[e._v("But it can also point directly to an "),a("code",[e._v("object")]),e._v(":")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[e._v("$ cat .git/HEAD\n4bb6f98a223abc9345a0cef9200562333\n\n")])])]),a("p",[e._v('This is what\'s known as a "detached head" - because '),a("code",[e._v("HEAD")]),e._v(" is not attached to (pointing at) any "),a("code",[e._v("ref")]),e._v(", but rather points directly to an "),a("code",[e._v("object")]),e._v(".")]),e._v(" "),a("h2",{attrs:{id:"refs"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#refs"}},[e._v("#")]),e._v(" Refs")]),e._v(" "),a("p",[e._v("A "),a("code",[e._v("ref")]),e._v(" is essentially a pointer. It's a name that points to an "),a("code",[e._v("object")]),e._v(". For example,")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[a("span",{pre:!0,attrs:{class:"token string"}},[e._v('"master"')]),e._v(" --\x3e 1a410e...\n\n")])])]),a("p",[e._v("They are stored in `.git/refs/heads/ in plain text files.")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[e._v("$ cat .git/refs/heads/mainline\n4bb6f98a223abc9345a0cef9200562333\n\n")])])]),a("p",[e._v("This is commonly what are called "),a("code",[e._v("branches")]),e._v(". However, you'll note that in "),a("code",[e._v("git")]),e._v(" there is no such thing as a "),a("code",[e._v("branch")]),e._v(" - only a "),a("code",[e._v("ref")]),e._v(".")]),e._v(" "),a("p",[e._v("Now, it's possible to navigate "),a("code",[e._v("git")]),e._v(" purely by jumping around to different "),a("code",[e._v("objects")]),e._v(" directly by their hashes. But this would be terribly inconvenient. A "),a("code",[e._v("ref")]),e._v(" gives you a convenient name to refer to "),a("code",[e._v("objects")]),e._v(" by. It's much easier to ask "),a("code",[e._v("git")]),e._v(" to go to a specific place by name rather than by hash.")]),e._v(" "),a("h2",{attrs:{id:"commit-object"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#commit-object"}},[e._v("#")]),e._v(" Commit Object")]),e._v(" "),a("p",[e._v("A "),a("code",[e._v("commit")]),e._v(" is probably the "),a("code",[e._v("object")]),e._v(" type most familiar to "),a("code",[e._v("git")]),e._v(" users, as it's what they are used to creating with the "),a("code",[e._v("git commit")]),e._v(" commands.")]),e._v(" "),a("p",[e._v("However, the "),a("code",[e._v("commit")]),e._v(" does not directly contain any changed files or data. Rather, it contains mostly metadata and pointers to other "),a("code",[e._v("objects")]),e._v(" which contain the actual contents of the "),a("code",[e._v("commit")]),e._v(".")]),e._v(" "),a("p",[e._v("A "),a("code",[e._v("commit")]),e._v(" contains a few things:")]),e._v(" "),a("ul",[a("li",[e._v("hash of a "),a("code",[e._v("tree")])]),e._v(" "),a("li",[e._v("hash of a parent "),a("code",[e._v("commit")])]),e._v(" "),a("li",[e._v("author name/email, commiter name/email")]),e._v(" "),a("li",[e._v("commit message")])]),e._v(" "),a("p",[e._v("You can see the contents of any commit like this:")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[a("span",{pre:!0,attrs:{class:"token command"}},[e._v("$ git cat-file commit 5bac93")]),e._v("\ntree 04d1daef...\nparent b7850ef5...\nauthor Geddy Lee \ncommiter Neil Peart \n\nFirst commit!\n\n")])])]),a("h3",{attrs:{id:"tree"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#tree"}},[e._v("#")]),e._v(" Tree")]),e._v(" "),a("p",[e._v("A very important note is that the "),a("code",[e._v("tree")]),e._v(" objects stores EVERY file in your project, and it stores whole files not diffs. This means that each "),a("code",[e._v("commit")]),e._v(" contains a snapshot of the entire project*.")]),e._v(" "),a("p",[e._v("*"),a("strong",[e._v("Technically, only changed files are stored. But this is more an implementation detail for efficiency. From a design perspective, a "),a("code",[e._v("commit")]),e._v(" should be considered as containing a complete copy of the project")]),e._v(".")]),e._v(" "),a("h3",{attrs:{id:"parent"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#parent"}},[e._v("#")]),e._v(" Parent")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("parent")]),e._v(" line contains a hash of another "),a("code",[e._v("commit")]),e._v(' object, and can be thought of as a "parent pointer" that points to the "previous commit". This implicitly forms a graph of commits known as the '),a("strong",[e._v("commit graph")]),e._v(". Specifically, it's a "),a("a",{attrs:{href:"https://en.wikipedia.org/wiki/Directed_acyclic_graph",target:"_blank",rel:"noopener noreferrer"}},[e._v("directed acyclic graph"),a("OutboundLink")],1),e._v(" (or DAG).")]),e._v(" "),a("h2",{attrs:{id:"tree-object"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#tree-object"}},[e._v("#")]),e._v(" Tree Object")]),e._v(" "),a("p",[e._v("A "),a("code",[e._v("tree")]),e._v(" basically represents a folder in a traditional filesystem: nested containers for files or other folders.")]),e._v(" "),a("p",[e._v("A "),a("code",[e._v("tree")]),e._v(" contains:")]),e._v(" "),a("ul",[a("li",[e._v("0 or more "),a("code",[e._v("blob")]),e._v(" objects")]),e._v(" "),a("li",[e._v("0 or more "),a("code",[e._v("tree")]),e._v(" objects")])]),e._v(" "),a("p",[e._v("Just as you can use "),a("code",[e._v("ls")]),e._v(" or "),a("code",[e._v("dir")]),e._v(" to list the contents of a folder, you can list the contents of a "),a("code",[e._v("tree")]),e._v(" object.")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[a("span",{pre:!0,attrs:{class:"token command"}},[e._v("$ git cat-file"),a("span",{pre:!0,attrs:{class:"token parameter"}},[e._v(" -p")]),e._v(" 07b1a631")]),e._v("\n100644 blob b91bba1b .gitignore\n100644 blob cc0956f1 Makefile\n040000 tree 92e1ca7e src\n...\n\n")])])]),a("p",[e._v("You can look up the files in a "),a("code",[e._v("commit")]),e._v(" by first finding the hash of the "),a("code",[e._v("tree")]),e._v(" in the "),a("code",[e._v("commit")]),e._v(", and then looking at that "),a("code",[e._v("tree")]),e._v(":")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[a("span",{pre:!0,attrs:{class:"token command"}},[e._v("$ git cat-file commit 4bb6f93a")]),e._v("\ntree 07b1a631\nparent ...\nauthor ...\ncommiter ... \n \n"),a("span",{pre:!0,attrs:{class:"token command"}},[e._v("$ git cat-file"),a("span",{pre:!0,attrs:{class:"token parameter"}},[e._v(" -p")]),e._v(" 07b1a631")]),e._v("\n100644 blob b91bba1b .gitignore\n100644 blob cc0956f1 Makefile\n040000 tree 92e1ca7e src\n...\n\n\n")])])]),a("h2",{attrs:{id:"blob-object"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#blob-object"}},[e._v("#")]),e._v(" Blob Object")]),e._v(" "),a("p",[e._v("A "),a("code",[e._v("blob")]),e._v(" contains arbitrary binary file contents. Commonly, it will be raw text such as source code or a blog article. But it could just as easily be the bytes of a PNG file or anything else.")]),e._v(" "),a("p",[e._v("If you have the hash of a "),a("code",[e._v("blob")]),e._v(", you can look at it's contents.")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[a("span",{pre:!0,attrs:{class:"token command"}},[e._v("$ git cat-file"),a("span",{pre:!0,attrs:{class:"token parameter"}},[e._v(" -p")]),e._v(" d429810")]),e._v("\npackage com.example.project\n\nclass Foo {\n ...\n}\n...\n\n")])])]),a("p",[e._v("For example, you can browse a "),a("code",[e._v("tree")]),e._v(" as above, and then look at one of the "),a("code",[e._v("blobs")]),e._v(" in it.")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[a("span",{pre:!0,attrs:{class:"token command"}},[e._v("$ git cat-file"),a("span",{pre:!0,attrs:{class:"token parameter"}},[e._v(" -p")]),e._v(" 07b1a631")]),e._v("\n100644 blob b91bba1b .gitignore\n100644 blob cc0956f1 Makefile\n040000 tree 92e1ca7e src\n100644 blob cae391ff Readme.txt\n\n"),a("span",{pre:!0,attrs:{class:"token command"}},[e._v("$ git cat-file"),a("span",{pre:!0,attrs:{class:"token parameter"}},[e._v(" -p")]),e._v(" cae391ff")]),e._v("\nWelcome to my project! This is the readmefile\n...\n\n")])])]),a("h2",{attrs:{id:"creating-new-commits"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#creating-new-commits"}},[e._v("#")]),e._v(" Creating new Commits")]),e._v(" "),a("p",[e._v("The "),a("code",[e._v("git commit")]),e._v(" command does a few things:")]),e._v(" "),a("ol",[a("li",[e._v("Create "),a("code",[e._v("blobs")]),e._v(" and "),a("code",[e._v("trees")]),e._v(" to represent your project directory - stored in "),a("code",[e._v(".git/objects")])]),e._v(" "),a("li",[e._v("Creates a new "),a("code",[e._v("commit")]),e._v(" object with your author information, commit message, and the root "),a("code",[e._v("tree")]),e._v(" from step 1 - also stored in "),a("code",[e._v(".git/objects")])]),e._v(" "),a("li",[e._v("Updates the "),a("code",[e._v("HEAD")]),e._v(" ref in "),a("code",[e._v(".git/HEAD")]),e._v(" to the hash of the newly-created "),a("code",[e._v("commit")])])]),e._v(" "),a("p",[e._v("This results in a new snapshot of your project being added to "),a("code",[e._v("git")]),e._v(" that is connected to the previous state.")]),e._v(" "),a("h2",{attrs:{id:"moving-head"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#moving-head"}},[e._v("#")]),e._v(" Moving HEAD")]),e._v(" "),a("p",[e._v("When you run "),a("code",[e._v("git checkout")]),e._v(" on a commit (specified by hash or ref) you're telling "),a("code",[e._v("git")]),e._v(" to make your working directory look like how it did when the snapshot was taken.")]),e._v(" "),a("ol",[a("li",[e._v("Update the files in the working directory to match the "),a("code",[e._v("tree")]),e._v(" inside the "),a("code",[e._v("commit")])]),e._v(" "),a("li",[e._v("Update "),a("code",[e._v("HEAD")]),e._v(" to point to the specified hash or ref")])]),e._v(" "),a("h2",{attrs:{id:"moving-refs-around"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#moving-refs-around"}},[e._v("#")]),e._v(" Moving refs around")]),e._v(" "),a("p",[e._v("Running "),a("code",[e._v("git reset --hard")]),e._v(" moves refs to the specified hash/ref.")]),e._v(" "),a("p",[e._v("Moving "),a("code",[e._v("MyBranch")]),e._v(" to "),a("code",[e._v("b8dc53")]),e._v(":")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[a("span",{pre:!0,attrs:{class:"token command"}},[e._v("$ git checkout MyBranch # moves HEAD to MyBranch")]),e._v("\n"),a("span",{pre:!0,attrs:{class:"token command"}},[e._v("$ git reset"),a("span",{pre:!0,attrs:{class:"token parameter"}},[e._v(" --hard")]),e._v(" b8dc53 # makes MyBranch point to b8dc53 ")]),e._v("\n\n")])])]),a("h2",{attrs:{id:"creating-new-refs"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#creating-new-refs"}},[e._v("#")]),e._v(" Creating new Refs")]),e._v(" "),a("p",[e._v("Running "),a("code",[e._v("git checkout -b ")]),e._v(" will create a new ref that points to the current "),a("code",[e._v("commit")]),e._v(".")]),e._v(" "),a("div",{staticClass:"language-git extra-class"},[a("pre",{pre:!0,attrs:{class:"language-git"}},[a("code",[e._v("$ cat .git/head\n1f324a\n\n"),a("span",{pre:!0,attrs:{class:"token command"}},[e._v("$ git checkout"),a("span",{pre:!0,attrs:{class:"token parameter"}},[e._v(" -b")]),e._v(" TestBranch")]),e._v("\n\n$ cat .git/refs/heads/TestBranch\n1f324a\n\n")])])])])}),[],!1,null,null,null);t.default=s.exports}}]);