{"id":324,"date":"2021-05-01T18:05:46","date_gmt":"2021-05-02T01:05:46","guid":{"rendered":"https:\/\/bornski.com\/maria\/blog\/?p=324"},"modified":"2022-11-21T13:54:04","modified_gmt":"2022-11-21T21:54:04","slug":"demystifying-git-git-commits","status":"publish","type":"post","link":"https:\/\/bornski.com\/maria\/blog\/2021\/05\/01\/demystifying-git-git-commits\/","title":{"rendered":"Demystifying Git &#8211; Git Commits"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">What is a git commit?<\/h2>\n\n\n\n<p>A git commit is the object that contains all the relevant information about your repository and files at the time of the commit.  Commits are the git objects you&#8217;ll interact with most frequently, and everything in our series will build on this knowledge.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Commit ID<\/h3>\n\n\n\n<p>Git uses <a href=\"https:\/\/en.wikipedia.org\/wiki\/SHA-1\">SHA-1<\/a> to calculate a hash of the commit object and the resulting hash becomes the commit ID.  If any information about your commit changes, the SHA-1 hash will change (unless you&#8217;re intentionally running a <a href=\"https:\/\/en.wikipedia.org\/wiki\/SHA-1#Attacks\">collision attack<\/a>, which is well outside the scope of this series, so we&#8217;ll ignore that possibility), thus resulting in a new commit object and a different commit ID.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-pretty-short-main.png\"><img decoding=\"async\" loading=\"lazy\" width=\"933\" height=\"523\" src=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-pretty-short-main.png\" alt=\"\" class=\"wp-image-327\" srcset=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-pretty-short-main.png 933w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-pretty-short-main-300x168.png 300w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-pretty-short-main-768x431.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><figcaption>Example git history with commit IDs<br>Command: &#8220;<code>git log --pretty=short<\/code>&#8220;<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Snapshot of your files<\/h3>\n\n\n\n<p>For each commit, git stores a snapshot of all the files in your repository.  This means that regardless of which files you changed in the commit, git can easily figure out the exact state of your repository at the time.<\/p>\n\n\n\n<p>Git uses a &#8220;tree&#8221; object to contain information about other objects in your repository and uses SHA-1 to create a tree ID for each tree object.  Any changes to the file contents, file names, or directory names in your repository will result in a different, thus resulting in a new tree ID for the new snapshot.  The &#8220;<a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Internals-Git-Objects\">Git Internals &#8211; Git Objects<\/a>&#8221; chapter of the &#8220;Pro Git&#8221; book has a great deep dive if you want to learn more about git objects.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-pretty-raw-ec74f0026.png\"><img decoding=\"async\" loading=\"lazy\" width=\"895\" height=\"707\" src=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-pretty-raw-ec74f0026.png\" alt=\"\" class=\"wp-image-328\" srcset=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-pretty-raw-ec74f0026.png 895w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-pretty-raw-ec74f0026-300x237.png 300w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-pretty-raw-ec74f0026-768x607.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><figcaption>Git log in raw mode with tree IDs highlighted<br>Command: <em>&#8220;<code>git log --pretty=raw ec74f0026<\/code><\/em>&#8220;<\/figcaption><\/figure>\n\n\n\n<p>While git stores a snapshot of your entire tree, most commands to view git commits and git history display only the differences between commits.  While this is often the information that someone wants to know, this method of display can mislead people into assuming git stores deltas or differences in the commit.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-ec74f0026.png\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"359\" src=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-ec74f0026-1024x359.png\" alt=\"\" class=\"wp-image-329\" srcset=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-ec74f0026-1024x359.png 1024w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-ec74f0026-300x105.png 300w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-ec74f0026-768x269.png 768w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-ec74f0026.png 1222w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><figcaption>Viewing a commit using &#8216;git show&#8217; displays a diff, not the full file tree<br>Command: &#8220;<code>git show ec74f00266dbf3a63288ca641f1f4325791567aa<\/code>&#8220;<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Who and When<\/h3>\n\n\n\n<p>Git stores information about who worked on a commit and when the commit was created.  Git was <a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Getting-Started-A-Short-History-of-Git\">originally designed<\/a> for Linux kernel development.  In the Linux kernel community, developers who would like to make a change write their code and then send the change to the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Linux_kernel_mailing_list\">Linux kernel mailing list<\/a> for discussion and code review.  Once the relevant maintainer  is satisfied, they <a href=\"https:\/\/en.wikipedia.org\/wiki\/Linux_kernel#Submitting_code_to_the_kernel\">incorporate the change into the kernel<\/a>.  This workflow means that more than one person is involved in every commit, so git keeps track of both Author and Committer information for each commit.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Author<\/h4>\n\n\n\n<p>The <code>Author<\/code> is the person who originally created the commit.  The <code>AuthorDate<\/code> is the timestamp of when the commit was originally created.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Committer<\/h4>\n\n\n\n<p>The <code>Committer<\/code> is the person who created this exact commit.  The <code>CommitDate<\/code> is the timestamp of when this exact commit was created.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Viewing and updating Author and Committer<\/h4>\n\n\n\n<p>You can view the <code>Author<\/code> and <code>Committer <\/code>information by adding <code>--pretty=fuller<\/code> to commands like <code>git log<\/code> and <code>git show<\/code>. When you first run <code>git commit<\/code> and create a commit object, the <code>Author<\/code> and <code>Committer <\/code>information will be the same.  <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-ec74f0026.png\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"397\" src=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-ec74f0026-1024x397.png\" alt=\"\" class=\"wp-image-330\" srcset=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-ec74f0026-1024x397.png 1024w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-ec74f0026-300x116.png 300w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-ec74f0026-768x297.png 768w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-ec74f0026.png 1273w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><figcaption>This commit has the same author and committer information<br>Command: <em>&#8220;<code>git show --pretty=fuller ec74f00266dbf3a63288ca641f1f4325791567aa<\/code>&#8220;<\/em><\/figcaption><\/figure>\n\n\n\n<p>Any changes to the commit via commands like <code>git cherry-pick<\/code>,  <code>git rebase<\/code>, or <code>git commit --amend<\/code> will update the <code>Committer<\/code> information but leave the <code>Author<\/code> information alone.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-734f7b3a2.png\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"417\" src=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-734f7b3a2-1024x417.png\" alt=\"Screenshot of output for &quot;git show --pretty=fuller 734f7b3a2&quot; from https:\/\/github.com\/mariabornski\/demystifying-git-examples\" class=\"wp-image-331\" srcset=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-734f7b3a2-1024x417.png 1024w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-734f7b3a2-300x122.png 300w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-734f7b3a2-768x313.png 768w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-fuller-734f7b3a2.png 1265w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><figcaption>This commit has different AuthorDate and CommitDate values.  This commit was cherry-picked from our prior commit (<em>ec74f0026<\/em>).<br>Command: <em>&#8220;<code>git show --pretty=fuller 734f7b3a208734237fe1cd9e89707a2c70a0969a<\/code>&#8220;<\/em><\/figcaption><\/figure>\n\n\n\n<p>By default, <code>git log<\/code> will display the <code>Author<\/code> and <code>AuthorDate<\/code>, which can make history look a bit surprising.  If you see a commit that says it was made earlier than the prior commit, it probably actually has a later <code>CommitDate<\/code>!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Parent commits<\/h3>\n\n\n\n<p>Git stores the commit ID(s) of any parent commits in each commit object.  The very first commit in a repository will not have a parent commit.  <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-raw-5504457e8.png\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"195\" src=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-raw-5504457e8-1024x195.png\" alt=\"Screenshot of output from &quot;git show --pretty=raw 5504457e8&quot; from https:\/\/github.com\/mariabornski\/demystifying-git-examples\" class=\"wp-image-332\" srcset=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-raw-5504457e8-1024x195.png 1024w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-raw-5504457e8-300x57.png 300w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-raw-5504457e8-768x146.png 768w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-show-pretty-raw-5504457e8.png 1271w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><figcaption>Our empty initial commit has no parent commit<br>Command: &#8220;<code>git show --pretty=raw 5504457e8df354fc66cee371b52cfa072153392a<\/code>&#8220;<\/figcaption><\/figure>\n\n\n\n<p>Merge commits will have multiple parent commits &#8212; One for each branched merged together.  Most commits will have a single parent commit: the most recent commit on the current branch in your working directory at the time you created the commit.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Commit message<\/h3>\n\n\n\n<p>The git commit message lets you explain your commit to your future self and other people looking at the repository.  As with all other aspects of the commit object, any changes to the commit message will result in a new commit ID.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How does this affect working with git?<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Comparing Commits<\/h3>\n\n\n\n<p>In the strictest sense, git commits are only the same if they are the literal same object &#8212; eg, they have the same commit ID.  Two commits may make exactly the same changes to your files but if they have different parent commits, commit messages, <code>Author<\/code> information, or <code>Committer<\/code> information, then they are <strong>not<\/strong> the same commit.  <\/p>\n\n\n\n<p>As a concrete example, these commits are identical except for <code>CommitterDate<\/code>.  They therefore have different commit IDs, so they are <strong>different<\/strong> commits.<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-2\">\n<div class=\"wp-block-column is-layout-flow\" style=\"flex-basis:100%\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-ec74f0026.png\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"596\" src=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-ec74f0026-1024x596.png\" alt=\"\" class=\"wp-image-334\" srcset=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-ec74f0026-1024x596.png 1024w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-ec74f0026-300x175.png 300w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-ec74f0026-768x447.png 768w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-ec74f0026.png 1152w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><figcaption>Command: &#8220;<code>git log -p -2 --pretty=fuller ec74f00266dbf3a63288ca641f1f4325791567aa<\/code>&#8220;<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-734f7b3a2.png\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"545\" src=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-734f7b3a2-1024x545.png\" alt=\"\" class=\"wp-image-335\" srcset=\"https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-734f7b3a2-1024x545.png 1024w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-734f7b3a2-300x160.png 300w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-734f7b3a2-768x409.png 768w, https:\/\/bornski.com\/maria\/blog\/wp-content\/uploads\/2021\/05\/git-log-p-pretty-fuller-2-734f7b3a2.png 1286w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><figcaption>Command: &#8220;<code>git log -p -2 --pretty=fuller 734f7b3a208734237fe1cd9e89707a2c70a0969a<\/code>&#8220;<\/figcaption><\/figure>\n<\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Other Impacts<\/h3>\n\n\n\n<p>We&#8217;ll talk more about how commit objects affect git workflows in future installments!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Try it for yourself!<\/h2>\n\n\n\n<p>All examples on this post were created using <a href=\"https:\/\/github.com\/mariabornski\/demystifying-git-examples\">https:\/\/github.com\/mariabornski\/demystifying-git-examples<\/a> and <code>git version 2.25.1<\/code> on <code>Ubuntu 20.04.1 LTS (GNU\/Linux 4.19.128-microsoft-standard x86_64<\/code>).<\/p>\n\n\n\n<p>You&#8217;re welcome to go clone the repository yourself &amp; try out the commands!  Similar commands will work on any git repository, you&#8217;ll just need to substitute your own commit IDs.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What is a git commit? A git commit is the object that contains all the relevant information about your repository and files at the time of the commit. Commits are the git objects you&#8217;ll interact with most frequently, and everything in our series will build on this knowledge. Commit ID Git uses SHA-1 to calculate &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/bornski.com\/maria\/blog\/2021\/05\/01\/demystifying-git-git-commits\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Demystifying Git &#8211; Git Commits&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[39,28],"tags":[40,34],"_links":{"self":[{"href":"https:\/\/bornski.com\/maria\/blog\/wp-json\/wp\/v2\/posts\/324"}],"collection":[{"href":"https:\/\/bornski.com\/maria\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bornski.com\/maria\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bornski.com\/maria\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bornski.com\/maria\/blog\/wp-json\/wp\/v2\/comments?post=324"}],"version-history":[{"count":5,"href":"https:\/\/bornski.com\/maria\/blog\/wp-json\/wp\/v2\/posts\/324\/revisions"}],"predecessor-version":[{"id":361,"href":"https:\/\/bornski.com\/maria\/blog\/wp-json\/wp\/v2\/posts\/324\/revisions\/361"}],"wp:attachment":[{"href":"https:\/\/bornski.com\/maria\/blog\/wp-json\/wp\/v2\/media?parent=324"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bornski.com\/maria\/blog\/wp-json\/wp\/v2\/categories?post=324"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bornski.com\/maria\/blog\/wp-json\/wp\/v2\/tags?post=324"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}