<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>commit on Digi Hunch</title><link>https://static.digihunch.com/tag/commit/</link><description>Recent content in commit on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Sat, 20 Jul 2024 16:40:44 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/commit/index.xml" rel="self" type="application/rss+xml"/><item><title>Common local Git operations</title><link>https://static.digihunch.com/2020/04/common-local-git-operations/</link><pubDate>Wed, 08 Apr 2020 11:54:00 -0400</pubDate><guid>https://static.digihunch.com/2020/04/common-local-git-operations/</guid><description>&lt;p class="wp-block-paragraph"&gt;This is a summary of concepts in common Git operations. We will discuss brach, merge, rebase, cherrypick, stash and reset. Then we&amp;#8217;ll discuss pull, fetch, and push.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-commit-branch-and-head"&gt;Commit, Branch and HEAD&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When you run &amp;#8220;git commit&amp;#8221;, the following happens:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Git checksums each subdirectory, and stores them as a tree object (file path and name) and blob object (file content) in Git repository;&lt;/li&gt;&lt;li&gt;Git creates a commit object that has the metadata and a pointer to the root project tree; or if this is not the first commit, the pointer will point to the commit immediately before it&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The operations above should form a chain of commit. It can be a long chain and may diverge into branches. In Git semantics however, a branch is simply a lightweight, movable pointer to one of the commits. The default branch name in Git is master. A Git repository may contain multiple branches and the name master itself does not suggest any privilege. There is also a special pointer called HEAD, which indicates the branch you are currently working on. So branch is essentially a pointer to a commit; HEAD is essentially a pointer to a branch. &amp;#8220;git checkout&amp;#8221; can switch branch that HEAD points to. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-basic-merge"&gt;Basic Merge&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;One type of basic merge simply moves branch pointer from one commit to another (along the same chain) without creating any commit. Here is a diagram before basic merge:&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://git-scm.com/book/en/v2/images/basic-branching-4.png" alt="Hotfix branch based on `master`."/&gt;&lt;figcaption&gt;Before basic merge, Hotfix branch is based on&amp;nbsp;&lt;code&gt;master&lt;/code&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The following command performs basic merge:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git checkout master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git merge hotfix&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Updating f42c576..3a0874c&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Fast-forward&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; index.html | 2 ++&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; 1 file changed, 2 insertions(+)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Then Git simply moves the pointer (named master) forward. There is no divergent work to move together, hence no chance of merge conflict. This type of basic merge is also called &amp;#8220;fast-forward&amp;#8221; merge.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://git-scm.com/book/en/v2/images/basic-branching-5.png" alt="`master` is fast-forwarded to `hotfix`."/&gt;&lt;figcaption&gt;After basic merge, &lt;code&gt;master&lt;/code&gt;&amp;nbsp;is fast-forwarded to&amp;nbsp;&lt;code&gt;hotfix&lt;/code&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The other type of merge involves reconciling divergent work together, which may or may not involve conflict. Suppose this is the commit tree to start with:&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://git-scm.com/book/en/v2/images/basic-merging-1.png" alt="Three snapshots used in a typical merge."/&gt;&lt;figcaption&gt;Three snapshots used in a typical merge&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The following commands perform the merge:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git checkout master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Switched to branch &amp;#39;master&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git merge iss53&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Merge made by the &amp;#39;recursive&amp;#39; strategy.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;index.html | 1 +&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;1 file changed, 1 insertion(+)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Instead of just moving the branch pointer forward, Git creates a new snapshot that results from this three-way merge and automatically creates a new commit that points to it. This is referred to as a merge commit, and is special in that it has more than one parent.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://git-scm.com/book/en/v2/images/basic-merging-2.png" alt="A merge commit."/&gt;&lt;figcaption&gt;A merge commit&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Now that your work is merged in, you have no further need for the&amp;nbsp;&lt;code&gt;iss53&lt;/code&gt;&amp;nbsp;branch. You can close the issue in your issue-tracking system, and delete the branch:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git branch -d iss53&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;If commits from two respective branches changes the same file in different ways, then there is a merge conflict. In this case, Git cannot just create a merge commit. Instead it asks the user to resolve the conflict first. You have to choose either side of the change, or just merge the content yourself. At this point, if you introduce a change that does not appear in any parent, it is referred to as an evil merge. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Beyond the basic merge, there are more sophisticated merge conflict resolution tools covered in &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging"&gt;advanced merging&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-merge-and-rebase"&gt;Merge and Rebase&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are two ways to integrate changes from one branch to another. Merge and rebase. Suppose your commit chain diverge into a master branch and a feature branch. Merging (from feature to master) takes the content of feature branch and integrate it with master branch. &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git checkout master&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git merge feature&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;When you rebase a feature branch onto master, you move the base of the feature branch to master branch’s ending point.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git checkout feature&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git rebase master&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;After merge, you are still &lt;span style="text-decoration: underline;"&gt;on the same branch&lt;/span&gt;. The commits from other branch are integrated into the branch that you are already on. There is no change in any existing commits (history). After rebase, your base will be &lt;span style="text-decoration: underline;"&gt;moved to a different branch&lt;/span&gt;, along with the commits that you have made in the previous branch (since the diverge). In other words, by re-playing those commits on a different branch, it changed history.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://miro.medium.com/max/855/1*pzT4KMiZDOFsMOKH-cJjfQ.png" alt=""/&gt;&lt;figcaption&gt;merge vs rebase&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The chart above is stolen from &lt;a href="https://hackernoon.com/git-merge-vs-rebase-whats-the-diff-76413c117333"&gt;this article&lt;/a&gt;, which does a better job explain in detail the difference, pros and cons of merge and rebase. Merge does create a &amp;#8220;merge commit&amp;#8221;, and a git history full of merges can be cluttered. Rebase does not create an extra commit but since it changes the history of a branch, it has impact to other collaborators. It can be done in an interactive way (with -i switch). The golden rules of rebasing is covered in &lt;a href="https://www.atlassian.com/git/tutorials/merging-vs-rebasing"&gt;this&lt;/a&gt; article. One of the principles is that never perform a rebase on a public branch.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="600" height="335" src="https://static.digihunch.com/wp-content/uploads/2020/08/0.gif" alt="" class="wp-image-1196"/&gt;&lt;figcaption&gt;git operations&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h3 class="wp-block-heading" id="h-cherrypick"&gt;Cherrypick&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In a cherrypick operation, the current branch does not change. You simply pick interested commits from other branches to re-apply to your current branch. You may pick a single or a series of commits from other branch. These commits are not &amp;#8220;moved&amp;#8221; to your current branch. They remain intact. They are just re-played as new commit to current branch. Unlike rebase, there is no re-writing of history, hence not as dangerous.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-reset-and-stash"&gt;Reset and Stash&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Suppose you are working on a part of a project and it starts getting messy. There has been an urgent bug that needs your immediate attention. It is time to save your changes and switch branches. If you are okay to give up your uncommitted work, you may perform a reset, in one of the three modes covered in a &lt;a href="https://static.digihunch.com/2019/06/git-explained-1-of-2/"&gt;previous article&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;But most likely, you don’t want to do a commit of half-done work. The solution is git stash. Stashing is handy if you need to quickly switch context and work on something else but you&amp;#8217;re mid-way through a code change and aren&amp;#8217;t quite ready to commit. In the most basic workflow, you need to run this command to save your uncommitted (but staged) work. As soon as you stash your change, the working directory is clean with all uncommitted local changes saved elsewhere. You can perform any other Git operations, such as change branch. When you&amp;#8217;re ready to resume, you may pop the stash. Here is an example:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git add .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git stash&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git checkout correctbranch&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git stash pop&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Instead of pop, you can also use apply to keep the changes in working directory. &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ git stash apply&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;More details are on &lt;a href="https://www.atlassian.com/git/tutorials/saving-changes/git-stash"&gt;this page&lt;/a&gt; from Bitbutket.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-fetch-and-pull"&gt;Fetch and Pull&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A git fetch simply downloads blob data from remote so the .git directory comes in sync with the server. It does not attempt to update the local working directory. If there is staged or uncommitted local changes, fetch will not impact them. &lt;strong&gt;A git pull is essentially git fetch followed by git merge&lt;/strong&gt;. In addition to downloading blob data, it also updates local working directory. Therefore, there is a chance of merge conflict when the same file has been modified locally. Git will usually guide you through the merge conflict by flagging the conflict area in the file and let you decide the survival changes. For example:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#! /usr/bin/env ruby&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;def hello&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&amp;lt; HEAD&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#39;hola world&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;=======&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; puts &lt;span style="color:#e6db74"&gt;&amp;#39;hello mundo&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; mundo&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;end&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hello&lt;span style="color:#f92672"&gt;()&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;You will be prompted in an editor session to reconcile the conflict. Once the file is saved, you will also need to do a &amp;#8220;merge commit&amp;#8221;, before you can pull again.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-push"&gt;Push&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Git push is the opposite of pull, where you merge local branch to the remote. (There is no opposite of fetch because there is no point to merge to remote without updating working directory, no collaborator works on the working directory on the server after all). If the local branch has fallen out of sync with the remote, there is a chance of merge error during git push. To minimize the chance of a merge during push, we can run a git pull before and reconcile any potential conflict locally. This is known as a pre-merge.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Visualizer&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I came across a great visualizer of commit chain &lt;a href="https://git-school.github.io/visualizing-git/"&gt;here&lt;/a&gt;. In the command panel type some git command and it will print the commit graph for you&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/03/ntlm-and-kerberos/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;NTLM and Kerberos protocols&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/04/how-memory-usage-adds-up-in-linux/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;How memory usage adds up in Linux&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Git Explained 1 of 2</title><link>https://static.digihunch.com/2019/06/git-explained-1-of-2/</link><pubDate>Sat, 08 Jun 2019 22:39:00 -0400</pubDate><guid>https://static.digihunch.com/2019/06/git-explained-1-of-2/</guid><description>&lt;p class="wp-block-paragraph"&gt;In a nutshell, Git is a distributed version control system, commonly used as source control management. It places files in one of three logical areas (working dir, staging, repo) below depending where it is in its lifecycle. &lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img loading="lazy" decoding="async" width="1618" height="992" src="https://static.digihunch.com/wp-content/uploads/2019/10/image.png" alt="" class="wp-image-178"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There are many cheetsheets out there but this article will just sort through some concepts unique to Git. To understand how Git works it is crucial to think in terms of Git data model.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Working directory&lt;/strong&gt; a single checkout of one version of the project. These files are pulled out of the object database in the Git directory (upon checkout) and placed in the project directory on disk, for you to use or modify;&amp;nbsp;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Index&lt;/strong&gt; a file contained in your Git directory (stored as binary data in file .git/index) that keeps information about what will go into your next commit.&amp;nbsp;To display what&amp;#8217;s in the index, run `git ls-files &amp;#8211;stage`. Read &lt;a href="https://hackernoon.com/https-medium-com-zspajich-understanding-git-data-model-95eb16cc99f5"&gt;this post&lt;/a&gt; for further details&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Repository&lt;/strong&gt;: where Git stores the metadata and &lt;code&gt;&lt;span style="text-decoration: underline;"&gt;object database&lt;/span&gt;&lt;/code&gt; for your project.&amp;nbsp;The local repository is in .git/ under the project directory.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Add&lt;/strong&gt; &amp;#8211; register one or more modified files to staging area. You may edit several files with only a few needed registered for future commit. Add activity ensures the file edited are recorded in the index (as a preview of next commit). You technically need to run add against each file. But the command syntax with * or . allows you to capture all edits in the same directory or under.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Commit&lt;/strong&gt; &amp;#8211; persist the staged file edits to the repository (so they are stored in Git object database). A commit represents all the file edits that were staged by add command in previous steps.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Branch&lt;/strong&gt; &amp;#8211; a branch is simply a movable pointer to a commit. Default branch name created by git init is called &amp;#8220;master&amp;#8221;. Other than the name, there is nothing special about master branch. Everytime you commit, the master branch pointer moves forward automatically. Branch pointers are kept in .git/refs directory. Read &lt;a href="https://hackernoon.com/understanding-git-branching-2662f5882f9"&gt;this post&lt;/a&gt; for further details.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;HEAD&lt;/strong&gt; &amp;#8211; the pointer to the current branch reference, which is in turn a pointer to the last commit made on that branch. Git use HEAD pointer to know what branch you&amp;#8217;re currently on. HEAD will be the parent of the upcoming commit.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Tag&lt;/strong&gt; &amp;#8211; an annotated tag contains the SHA of the commit being tagged. Alias of a commit.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Merge&lt;/strong&gt; &amp;#8211; choose current commit of other branch and apply it onto your branch.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Rebase&lt;/strong&gt; &amp;#8211; copy all commits from other branch to your branch. Compared to merge, rebasing forms a cleaner commit history.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Cherrypick&lt;/strong&gt; &amp;#8211; choose a previous commit from other branch and apply it onto your branch.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Stash&lt;/strong&gt; &amp;#8211; &amp;nbsp;temporarily stashes changes you&amp;#8217;ve made to working tree so you can work on something else, and then come back and re-apply them later on.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Reset&lt;/strong&gt; &amp;#8211; at a high level, reset is to revert some operations. After pulling code, developer usually follow three steps: editing-&amp;gt;add-&amp;gt;commit. reset is to reverse these steps, based on different modes. The Pro Git reference has further details on the &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified"&gt;three different modes&lt;/a&gt;:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;soft mode&lt;/strong&gt; (reverse operation of commit): based on what branch HEAD points to, move where that branch points to (e.g. from latest commit, to a different commit several steps up the link);&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;mixed mode&lt;/strong&gt; (default; reverse operation of commit and add) &amp;#8211; in addition to soft mode, also update index;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;hard mode&lt;/strong&gt; (reverse operation of commit, add and file editing)- in addition to mixed mode, also update working directory. Edit on files are discarded.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Git object model&lt;/strong&gt; &amp;#8211; In Git database, files, commits and directories are stored as objects, In Git &lt;a href="https://shafiul.github.io/gitbook/1_the_git_object_model.html"&gt;object model&lt;/a&gt;, there are three types (to tell object type, run `git cat-file -t`). Read &lt;a href="https://hackernoon.com/https-medium-com-zspajich-understanding-git-data-model-95eb16cc99f5"&gt;this post&lt;/a&gt; for further details:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;blob object&lt;/strong&gt; &amp;#8211; stores file data with metadata; use `git show` to examine blob object;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;tree object&lt;/strong&gt; &amp;#8211; represents a directory. It references other tree objects (sub-directories) or blob objects (files under the directory, of a certain version); use `git ls-tree` to examine tree object;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;commit object&lt;/strong&gt; &amp;#8211; represents a commit. It references its parent commit, as well as a tree object that represents the entire project directory. use `git cat-file -p` to inspect commit object;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This &lt;a href="https://git-scm.com/book/en/v2/Git-Internals-Git-Objects"&gt;diagram&lt;/a&gt; from from Git Pro outlines the interactions amongst these types of objects.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://git-scm.com/book/en/v2/images/data-model-3.png" alt="All the reachable objects in your Git directory."/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;For more details&lt;/strong&gt;, the&amp;nbsp;&lt;a href="https://git-scm.com/book/en/v2"&gt;official documentation&lt;/a&gt;&amp;nbsp;is actually the most helpful reference with illustrations. In addition, I find on Hakcermoon three excellent articles with thorough explanation on&amp;nbsp;&lt;a href="https://hackernoon.com/https-medium-com-zspajich-understanding-git-data-model-95eb16cc99f5"&gt;data model&lt;/a&gt;,&amp;nbsp;&lt;a href="https://hackernoon.com/understanding-git-branching-2662f5882f9"&gt;branching&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href="https://hackernoon.com/understanding-git-index-4821a0765cf"&gt;index&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2019/05/automation-with-ansible-a-primer/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Set up automation with Ansible&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2019/06/git-explained-2-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Git Explained 2 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>