<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: s-heins</title>
    <description>The latest articles on Forem by s-heins (@sheins).</description>
    <link>https://forem.com/sheins</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F682196%2Fa4f08645-c844-4d75-a972-731b3505aede.png</url>
      <title>Forem: s-heins</title>
      <link>https://forem.com/sheins</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sheins"/>
    <language>en</language>
    <item>
      <title>A deeper look: Git behind the scenes</title>
      <dc:creator>s-heins</dc:creator>
      <pubDate>Fri, 10 Dec 2021 15:18:36 +0000</pubDate>
      <link>https://forem.com/sheins/a-deeper-look-git-behind-the-scenes-50kb</link>
      <guid>https://forem.com/sheins/a-deeper-look-git-behind-the-scenes-50kb</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/sheins/-a-practical-introduction-to-git-jumping-in-with-both-feet-2o56"&gt;first article&lt;/a&gt;, we have looked at how to initialize a git repo locally, add and commit, and set some configuration options.&lt;br&gt;
Next, the second article covered how to work with remotes and branches, how to resolve conflicts, and how to merge and delete branches both from the CLI or from the GitHub UI.&lt;/p&gt;

&lt;p&gt;Now that we have gained some overview over the basic functions of git, it is time for an excursion into some basics on how git works behind the scenes. How does git notice that a file has changed so that it can show us this in our status? How does git realize branches? How does git know the order of the commits in each branch? What is HEAD and what is this mysterious detached HEAD state? And most importantly, how do I get out of this state again?&lt;/p&gt;

&lt;p&gt;As a resource for this article, I have used the &lt;a href="https://git-scm.com/book/en/v2"&gt;Pro Git book, written by Scott Chacon and Ben Straub&lt;/a&gt; which is available for free and may be shared non-commercially.&lt;/p&gt;

&lt;p&gt;Because the details of how git works exactly can easily make up a book (as seen above), we will only look deeply enough in this article to set the stage for more advanced git maneuvers such as rebasing, where you replay your work on top of a different commit than the one you originally set out from, and to give some context to the commands we have covered in the first two articles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How does git know a file has changed?&lt;/li&gt;
&lt;li&gt;
File status lifecycle and git project sections

&lt;ul&gt;
&lt;li&gt;Git project sections&lt;/li&gt;
&lt;li&gt;Git file status lifecycle&lt;/li&gt;
&lt;li&gt;One file can have multiple changes in different states at once&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Anatomy of a commit&lt;/li&gt;
&lt;li&gt;Back to the start – creating a repository&lt;/li&gt;
&lt;li&gt;
References

&lt;ul&gt;
&lt;li&gt;Branches&lt;/li&gt;
&lt;li&gt;Tags&lt;/li&gt;
&lt;li&gt;HEAD&lt;/li&gt;
&lt;li&gt;Detached HEAD state&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Conclusion and command summary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cover image by &lt;a href="https://m.facebook.com/story.php?story_fbid=10158229224234519&amp;amp;id=501159518"&gt;Jeremy Francis&lt;/a&gt; (with permission)&lt;/p&gt;
&lt;h2&gt;
  
  
  How does git know a file has changed?
&lt;/h2&gt;

&lt;p&gt;Git does not store the exact differences between files (for example, add the line "house cat" to your file "list-of-animals-to-write-about"), but rather, it stores &lt;strong&gt;snapshots&lt;/strong&gt;. For this example, git has a snapshot of the file before adding that line and then compares it to the current version of the file to figure out if something has changed.&lt;/p&gt;

&lt;p&gt;To do this, git computes a SHA-1 hash value based on the contents for each file and uses it for checksumming. SHA-1 is a cryptographic hash function that makes it highly unlikely to create the same hash for two different files, so if the hash is the same, we can assume that it was created based on the same input. If the checksum of a file has changed, the file itself must have changed. If a file was deleted and another was added but they share the same checksum, they must have the same contents – this is how git knows that a file was renamed. If the contents of a file have changed, the name will be the same but its hash will be different.&lt;/p&gt;

&lt;p&gt;In case a file has not changed at all in a commit, git will not store the file itself again, just a link to the one it has already saved in a previous snapshot.&lt;/p&gt;
&lt;h2&gt;
  
  
  File status lifecycle and git project sections
&lt;/h2&gt;

&lt;p&gt;In the first article, we have already added and committed files and file changes. Git has three states for any file it already knows about: &lt;strong&gt;modified&lt;/strong&gt;, &lt;strong&gt;staged&lt;/strong&gt;, and &lt;strong&gt;committed&lt;/strong&gt;. It then also has a fourth state for any files it doesn't know about: &lt;strong&gt;untracked&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's now look at what different states a file is in, from its creation, adding it, and finally committing it. We will use &lt;code&gt;git status&lt;/code&gt; to check which status our file is in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9QfdfmE5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wxyogb1kqs50s1uyh8lc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9QfdfmE5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wxyogb1kqs50s1uyh8lc.png" alt="Different git states when creating, adding, and committing a file" width="880" height="979"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Git project sections
&lt;/h3&gt;

&lt;p&gt;As a file goes through its lifecycle, it will also travel through different sections of our git project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Working directory&lt;/strong&gt;: After adding &lt;code&gt;new-file&lt;/code&gt;, the file is present in our directory and &lt;strong&gt;untracked&lt;/strong&gt;, that means that we created a new file git doesn't know about yet. Any existing files we change will be in the &lt;strong&gt;modified&lt;/strong&gt; state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Staging area&lt;/strong&gt;: After &lt;code&gt;git add .&lt;/code&gt;, the changes are now marked as &lt;strong&gt;staged&lt;/strong&gt; and are in the staging area. This is also called the &lt;strong&gt;index&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository&lt;/strong&gt;: After we &lt;code&gt;git commit&lt;/code&gt; our changes, they will be added to our local &lt;code&gt;.git&lt;/code&gt; repository as &lt;strong&gt;committed&lt;/strong&gt;. We can also push them to add them to our remote repository.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Git file status lifecycle
&lt;/h3&gt;

&lt;p&gt;We can now look at the file states with regards to sections in the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Untracked&lt;/strong&gt; (Working Directory)
Files that are not in the staging area and not in your last snapshot (= commit), i.e. files that git doesn't yet know about.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modified&lt;/strong&gt; (Working Directory)
Files that have been modified since the last commit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Staged&lt;/strong&gt; (Staging Area)
Untracked or modified files that were added to the Staging area by &lt;code&gt;git add&lt;/code&gt;ing them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Committed&lt;/strong&gt; (Repository)
Files that were committed to the repository by running &lt;code&gt;git commit&lt;/code&gt; after they were moved to the staging area.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any committed files will move back to the &lt;em&gt;modified&lt;/em&gt; state after we have changed them, and from there, they can move through the lifecycle again. Any unmodified files will still be in the &lt;em&gt;committed&lt;/em&gt; state, so safely stored in your git database (so your local &lt;code&gt;.git&lt;/code&gt; folder and, if you have set up a remote and pushed your commit to it, also in your upstream repository).&lt;/p&gt;

&lt;p&gt;If you have any modified files for which you want to skip the staging area, you can run &lt;code&gt;git commit -a&lt;/code&gt; so that git will commit all tracked files without you having to &lt;code&gt;add&lt;/code&gt; them first. This does not work for any untracked files, however.&lt;/p&gt;
&lt;h3&gt;
  
  
  One file can have multiple changes in different states at once
&lt;/h3&gt;

&lt;p&gt;Git uses the file status to communicate to us what the status of our files is. However, a file can also have multiple states – we could do some preliminary changes, add them to the staging area, and then do some more changes. In that case, git will have multiple snapshots of that file, one snapshot per commit where that file changed, another snapshot for the staged version, and yet another one for the working directory version of our file.&lt;br&gt;
Git will then show us that the file has some changes that are to be committed and some other changes that are not yet staged:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_Yio9tWe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dew53gaxhsluzn5jqscp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_Yio9tWe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dew53gaxhsluzn5jqscp.png" alt="Making some changes to a file, adding them to the staging area, and making more changes to the file" width="880" height="481"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Anatomy of a commit
&lt;/h2&gt;

&lt;p&gt;As discussed before, git stores &lt;strong&gt;snapshots&lt;/strong&gt;. Specifically, git stores files as &lt;code&gt;blobs&lt;/code&gt; (binary large objects) within git, as well as the checksums of their file contents and header. Then, it builds a &lt;strong&gt;tree object&lt;/strong&gt; (the root project tree) that models the directory structure.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;commit&lt;/strong&gt; then stores some meta information and a &lt;strong&gt;pointer&lt;/strong&gt; to that root tree.&lt;/p&gt;

&lt;p&gt;Commit metadata includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;author of the commit (i.e. the person that wrote or changed the respective lines)&lt;/li&gt;
&lt;li&gt;the committer (the person who committed the work of the author)&lt;/li&gt;
&lt;li&gt;the parent of the commit (if it has one) – this is a pointer to a commit hash&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the example further below, we will see when author and committer can differ: For the merge commit we're going to be looking at, I am the author but GitHub committed for me since I executed the merge on the GitHub UI. Another example would be if someone &lt;em&gt;rebases&lt;/em&gt; my commits on top of another parent. That means that they will take my work and replay it on top of another parent than the one I used originally. We will focus on such advanced git maneuvers in a subsequent article.&lt;/p&gt;

&lt;p&gt;Since every commit contains a reference to its parent (if it has one), we can think of commits as a tree where each commit has between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;n&lt;/code&gt; parents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a commit has zero parents, it is the very first commit.&lt;/li&gt;
&lt;li&gt;If it has two (or more), it is a merge commit. Usually, two branches would be merged so that the resulting commit would have two parents but it is also possible (albeit unusual) to merge more than two branches.&lt;/li&gt;
&lt;li&gt;If a commit has one parent, it is a "normal" commit, i.e. neither a merge commit nor the very first commit in a repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's say our collaborators Anna and Wolfgang have been busy and our git tree currently looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZqZ0aHE7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bk2jp9wslyfeqmflwia8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZqZ0aHE7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bk2jp9wslyfeqmflwia8.png" alt="The current git tree" width="880" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hint if you have not read the previous articles:&lt;br&gt;
To be able to use the &lt;code&gt;lg&lt;/code&gt; command alias, add this line to your &lt;code&gt;~/.gitconfig&lt;/code&gt; file under the [alias] section:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
lg &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;clear &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git log &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'format:%C(auto)%h%d %s  %C(magenta)[%an] (%ad)%C(reset)'&lt;/span&gt; &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s1"&gt;'%d.%m.%y %H:%M'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;In this example, we have merged the branch "articles-on-animals-from-list" into "main" and the commit &lt;code&gt;2cca46a&lt;/code&gt; (that is also labeled as HEAD on the screenshot) is a merge commit. At the very bottom of the screenshot, &lt;code&gt;98369a7&lt;/code&gt; ("Add a house cat") is the first commit and has no parent, and all other commits in between have only one parent. The commits &lt;code&gt;0a6ebca&lt;/code&gt; and &lt;code&gt;b9eb6d0&lt;/code&gt; have the same parent, but they only have one parent: Our merge commit that we have currently checked out and is the last commit on the main branch.&lt;/p&gt;

&lt;p&gt;If you also want to look at the same commit data as me in this article, you can clone my &lt;code&gt;git-encyclopedia-example&lt;/code&gt; project &lt;a href="https://github.com/s-heins/git-encyclopedia-example"&gt;on GitHub&lt;/a&gt; by running &lt;code&gt;git clone https://github.com/s-heins/git-encyclopedia-example.git&lt;/code&gt; (to clone via HTTPS).&lt;/p&gt;

&lt;p&gt;To look at &lt;code&gt;commit&lt;/code&gt; metadata, we can use &lt;code&gt;git cat-file -p&lt;/code&gt;, where &lt;code&gt;-p&lt;/code&gt; lets us pretty-print the object's content.&lt;br&gt;
I'm saying "object" because git stores multiple pieces of information as objects – such as &lt;code&gt;blob&lt;/code&gt; objects for files, &lt;code&gt;commit&lt;/code&gt; objects, and &lt;code&gt;tree&lt;/code&gt; objects which allow us to reference other &lt;code&gt;tree&lt;/code&gt; objects and &lt;code&gt;blob&lt;/code&gt; objects to model a file tree. (Any children &lt;code&gt;tree&lt;/code&gt; objects would then represent folders and &lt;code&gt;blob&lt;/code&gt; objects would be files). To read more about this, see &lt;a href="https://git-scm.com/book/en/v2/Git-Internals-Git-Objects"&gt;chapter 10.2 in the pro git book&lt;/a&gt;. The fourth type of git objects are &lt;em&gt;annotated tags&lt;/em&gt; which we will discuss soon when we talk about &lt;em&gt;references&lt;/em&gt; in git. For short, we will refer to &lt;em&gt;annotated tags&lt;/em&gt; as just tags in the following text.&lt;/p&gt;

&lt;p&gt;Types of git objects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blob&lt;/li&gt;
&lt;li&gt;commit&lt;/li&gt;
&lt;li&gt;tree&lt;/li&gt;
&lt;li&gt;tag&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can use &lt;code&gt;git cat-file -p&lt;/code&gt; to look at our merge commit, &lt;code&gt;2cca46a&lt;/code&gt; for example, where we will see that it has two parents and what their commit hashes are. As mentioned before, we can also see that in this case, author and committer are different because I created the merge commit via the GitHub UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yUC1Ezby--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/quhrj5gd3q9sy1ho7xg8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yUC1Ezby--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/quhrj5gd3q9sy1ho7xg8.png" alt="Using git cat-file -p to look at commit metadata" width="880" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When git gave us some information about our commit before, it not only included information on the parent commit hashes, the author, and committer, but it also listed an object hash for the root tree that models the directory structure.&lt;/p&gt;

&lt;p&gt;From this tree, we can look at the different sub-trees (subdirectories) and files with the command &lt;code&gt;git ls-tree -rt&lt;/code&gt;, where the &lt;code&gt;-r&lt;/code&gt; flag will recurse into subdirectories and the &lt;code&gt;-t&lt;/code&gt; flag will include trees when recursing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git ls-tree &lt;span class="nt"&gt;-rt&lt;/span&gt; 240e206

100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    alligator
100644 blob 4b92c463e35f265b9b43f5beebc9e02df815efb2    animals-to-write-about
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    chimpanzee
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    crocodile
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    elephant
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    giraffe
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    gorilla
100644 blob 3be11c69355948412925fa5e073d76d58ff3afd2    house-cat.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    tiger.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our example, we do not have any directories yet, so git only lists blob objects here.&lt;br&gt;
So let's move all of Wolfgang's articles into a travel directory and look at the tree again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s1"&gt;'Move cities articles into travel subdirectory'&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;ENC-002_capital-cities-in-europe cafdadd] Move cities articles into travel subdirectory
 4 files changed, 0 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;, 0 deletions&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="o"&gt;)&lt;/span&gt;
 rename albania-tirana.md &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; travel/albania-tirana.md &lt;span class="o"&gt;(&lt;/span&gt;100%&lt;span class="o"&gt;)&lt;/span&gt;
 rename austria-vienna.md &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; travel/austria-vienna.md &lt;span class="o"&gt;(&lt;/span&gt;100%&lt;span class="o"&gt;)&lt;/span&gt;
 rename belarus-minsk.md &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; travel/belarus-minsk.md &lt;span class="o"&gt;(&lt;/span&gt;100%&lt;span class="o"&gt;)&lt;/span&gt;
 rename germany-berlin.md &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; travel/germany-berlin.md &lt;span class="o"&gt;(&lt;/span&gt;100%&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the commit hash that git tells us in the output, &lt;code&gt;cafdadd&lt;/code&gt;, we can run &lt;code&gt;git cat-file -p cafdadd&lt;/code&gt; and find out the hash of the root tree, which we can use for the ls-tree command afterwards. To keep the list a bit shorter, we can tell git to abbreviate the object hashes by using the &lt;code&gt;--abbrev=&amp;lt;digits&amp;gt;&lt;/code&gt; flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git ls-tree &lt;span class="nt"&gt;-rt&lt;/span&gt; &lt;span class="nt"&gt;--abbrev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7 8ec6421

100644 blob e69de29 alligator
100644 blob 4b92c46 animals-to-write-about
100644 blob e69de29 chimpanzee
100644 blob e69de29 crocodile
100644 blob e69de29 elephant
100644 blob e69de29 giraffe
100644 blob e69de29 gorilla
100644 blob 3be11c6 house-cat.md
100644 blob e69de29 tiger.md
040000 tree ea0789f travel
100644 blob e69de29 travel/albania-tirana.md
100644 blob e69de29 travel/austria-vienna.md
100644 blob e69de29 travel/belarus-minsk.md
100644 blob 1038ae6 travel/germany-berlin.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since our encyclopedia authors were a bit lazy here and have not actually added contents to these files, a lot of files share the same object hash (&lt;code&gt;e69de29&lt;/code&gt;) – they are all empty.&lt;/p&gt;

&lt;p&gt;If we do not use the flag to recurse into subtrees, git will show us that the root tree object only contains information on the animal article blob objects and the travel tree object, and not on the travel article blobs. The information about them will be contained in the travel tree, &lt;code&gt;ea0789f&lt;/code&gt;, so the hierarchy of these objects looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── commit cafdadd 
│   └── tree 8ec6421
│       ├── blob e69de29 alligator
│       ├── blob 4b92c46 animals-to-write-about
│       ├── blob e69de29 chimpanzee
│       ├── &lt;span class="c"&gt;# … (other articles on animals)&lt;/span&gt;
│       └── tree ea0789f travel
│            ├── blob e69de29 albania-tirana.md
│            ├── blob e69de29 austria-vienna.md 
│            ├── blob e69de29 belarus-minsk.md 
│            └── blob 1038ae6 germany-berlin.md 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To find out a bit more on what happens to git objects as we add and commit them, see &lt;a href="https://dev.to/sheins/git-blob-and-tree-objects-during-the-status-lifecycle-1mmd"&gt;this article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to the start – creating a repository
&lt;/h2&gt;

&lt;p&gt;As mentioned in the &lt;a href="https://dev.to/sheins/-a-practical-introduction-to-git-jumping-in-with-both-feet-2o56"&gt;first article&lt;/a&gt;, git adds a &lt;code&gt;.git&lt;/code&gt; folder in your working directory when you run the &lt;code&gt;git init&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MP0oT6KF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3z3uyehcv6mm5ae3qygj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MP0oT6KF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3z3uyehcv6mm5ae3qygj.png" alt="Initializing the repository creates a hidden  raw `.git` endraw  folder" width="880" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can now find all our commits in the &lt;code&gt;objects&lt;/code&gt; folder within the &lt;code&gt;.git&lt;/code&gt; folder. Git saves these objects in folders that carry the first two characters of the object hash. The rest of the characters are used as the file name within that folder. For example, our commit &lt;code&gt;2cca46a&lt;/code&gt; which we looked at with &lt;code&gt;cat-file&lt;/code&gt; is really called &lt;code&gt;2cca46ab8626e867e2994cac12eb97887b0a82a2&lt;/code&gt; in full but it is enough to use the short name because there are no other git objects whose name also starts with &lt;code&gt;2cca46a&lt;/code&gt;. The information for this commit will be contained in a file within the &lt;code&gt;2c&lt;/code&gt; folder inside the &lt;code&gt;objects&lt;/code&gt; folder, and this file will be called &lt;code&gt;ca46ab8626e867e2994cac12eb97887b0a82a2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OFlo7OMq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqrcyfu2h5yvlvn06vrm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OFlo7OMq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mqrcyfu2h5yvlvn06vrm.png" alt="Looking at a git commit file inside the objects folder" width="880" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;Like in programming, git references point to other things. This could be a commit if we're talking about a branch reference or a tag, or it could be another reference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Branches
&lt;/h3&gt;

&lt;p&gt;In case you want to work together with someone, you could always send them the name of your latest commit and they could then check out that commit. That would be a lot of hassle, however, since you would have to keep messaging them any time you make a change to tell them the newest commit hash, and they would need to check their messages constantly. At this rate, no one would want to work with us on any projects and the world would be a sad place.&lt;/p&gt;

&lt;p&gt;To make things a lot easier, we can refer to a line of work with branches. Behind the scenes, a branch is just a reference to a commit with the added bonus that if you add a child to this commit, the reference gets advanced to this latest commit. The commit the reference points to then carries information about its parent commits but the branch itself is just a pointer to the latest commit, the so-called &lt;strong&gt;head&lt;/strong&gt;. That means that git just infers which commits belong to a branch based on the commit the branch points to and its parent(s) and their parent(s). Git can show us where our branch diverged from main by going backward from the head to its parents and showing us those commits which are not contained in the main branch, i.e. which are not the commit that the main branch points to nor parents of it.&lt;/p&gt;

&lt;p&gt;Git saves all information about references in the &lt;code&gt;refs&lt;/code&gt; folder. Any references for our remotes are contained within &lt;code&gt;.git/refs/remotes/origin&lt;/code&gt;. As we can also see in our git tree visualization in the command line, &lt;code&gt;main&lt;/code&gt; points to &lt;code&gt;75616f3&lt;/code&gt;, the &lt;code&gt;ENC-003…&lt;/code&gt; reference points to &lt;code&gt;f82574d&lt;/code&gt;, and the &lt;code&gt;ENC-002…&lt;/code&gt; reference points to &lt;code&gt;94a47c8&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hVKYmcLm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/od64wjiqu1wa8nqk25yk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hVKYmcLm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/od64wjiqu1wa8nqk25yk.png" alt="Git tree and branch references" width="880" height="698"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we look at just the commits in our branch and compare them to the graph view, we can see that our &lt;code&gt;ENC-002&lt;/code&gt; branch and &lt;code&gt;main&lt;/code&gt; share a few commits (orange in the screenshot) and they also have some commits that only belong only to them (green in the screenshot). In the tree view above it might seem like &lt;code&gt;ENC-002&lt;/code&gt; only began with commit &lt;code&gt;b6eb6d0 (Add article on Tirana in Albania)&lt;/code&gt; but really, it contains all commits that came before.&lt;br&gt;
When we merge this branch to main then, git will create a merge commit that has the latest branch commit and the latest main commit as parents as we can see in our example in the merge commit &lt;code&gt;2ca46a (Merge pull request #1…)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lGl7YoZi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wj5jb2smr19o9niaakmn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lGl7YoZi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wj5jb2smr19o9niaakmn.png" alt="Git log of commits for each branch" width="880" height="683"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Tags
&lt;/h3&gt;

&lt;p&gt;Tags are very similar to branches in that they &lt;em&gt;reference a commit&lt;/em&gt;. However, while &lt;em&gt;a branch reference auto-advances when you push a new commit&lt;/em&gt; on top of the one that the branch currently points to, &lt;em&gt;tags stay fixed&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This is handy if you work with releases for your software and you want to mark a certain commit as a specific version. Then, it would be rather annoying if your tag kept moving as you added more commits; you'd have no way of finding out which commit was associated with your release for version 1.2.4, for example.  &lt;/p&gt;

&lt;p&gt;To add a tag to your commit, run &lt;code&gt;git tag -a "your tag name"&lt;/code&gt;. Afterwards, git will open your default CLI text editor such as nano or vim to let you write a tag message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--08qMw1ga--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bkpb766d6us8luzdatx1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--08qMw1ga--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bkpb766d6us8luzdatx1.png" alt="Adding a tag to a commit" width="880" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After we have added the tag, we can now add more commits on top and we can see that while the branch reference has moved, the tag reference has not.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W0Qwf0BC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8wmt7n41zmqvs79ieo03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W0Qwf0BC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8wmt7n41zmqvs79ieo03.png" alt="Adding a commit on top of a tagged commit" width="880" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To learn more about tags and other references, have a look at &lt;a href="https://git-scm.com/book/en/v2/Git-Internals-Git-References#tags"&gt;chapter 10.3&lt;/a&gt; of the git pro book.&lt;/p&gt;
&lt;h3&gt;
  
  
  HEAD
&lt;/h3&gt;

&lt;p&gt;Before, we mentioned that the latest branch in a commit is also called a head. Git stores information on the currently checked out commit or reference in the &lt;code&gt;HEAD&lt;/code&gt; file within the &lt;code&gt;.git&lt;/code&gt; folder. In case we currently have a branch checked out, head will refer to this branch, so &lt;code&gt;HEAD&lt;/code&gt; will be a reference to our branch reference.&lt;br&gt;
We can also use &lt;code&gt;HEAD&lt;/code&gt; within git to refer to our branch. So instead of using &lt;code&gt;git push origin ENC-002_capital-cities-in-europe&lt;/code&gt;, we can also run this following command if we have currently checked out our branch &lt;code&gt;ENC-002…&lt;/code&gt; and we want to push it to our upstream repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-u&lt;/code&gt; flag is a shorthand for &lt;code&gt;--set-upstream&lt;/code&gt; which tells git to add our local branch to the upstream repository. Afterwards, we specify our remote repository that git should push to. In most cases this will be called &lt;code&gt;origin&lt;/code&gt;; in our repo it is also called origin because we told git to call our upstream "origin" when we ran &lt;code&gt;git remote add origin &amp;lt;repository-address&amp;gt;&lt;/code&gt;.&lt;br&gt;
Finally, &lt;code&gt;HEAD&lt;/code&gt; is our pointer that points to our branch reference which in turn points to our latest commit (if we have currently checked out a branch).&lt;br&gt;
Git will now create a branch on origin which is called the same as our local branch and points to the same commit.&lt;/p&gt;

&lt;p&gt;In the background, git stores information on HEAD in the &lt;code&gt;.git/HEAD&lt;/code&gt; file. When we run &lt;code&gt;cat .git/HEAD&lt;/code&gt;, git tells us that our &lt;code&gt;HEAD&lt;/code&gt; is a reference which points to another reference, namely &lt;code&gt;ENC-002…&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n2z1_T1H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/89pw0g698e4jjw36wujh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n2z1_T1H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/89pw0g698e4jjw36wujh.png" alt="Git tells us which branch HEAD points to when we look at the HEAD file in the .git folder" width="880" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Detached HEAD state
&lt;/h3&gt;

&lt;p&gt;Most of the time, &lt;code&gt;HEAD&lt;/code&gt; will point to a branch reference which points to the latest commit in a branch but there is also such a thing as &lt;strong&gt;detached HEAD state&lt;/strong&gt; where &lt;code&gt;HEAD&lt;/code&gt; will point to a commit which is not the head of a branch. You move into detached head state by checking out a commit that no branch reference points to and you can move out of it again by either creating a new branch (whose reference will then point to this commit), or by checking out an existing branch.&lt;/p&gt;

&lt;p&gt;In the following example, I checked out a previous commit that was not the head of any branch, added and committed a file and created a new branch to move out of detached head state again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TWrOOF4A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8j377xpckvqgme5xj7e3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TWrOOF4A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8j377xpckvqgme5xj7e3.png" alt="Getting out of detached head state" width="880" height="873"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and command summary
&lt;/h2&gt;

&lt;p&gt;In this article, we looked at the different file states (unmodified/committed, untracked, modified, and staged). We saw that each commit contains information on its author, committer and parent commit(s) and how git branches work. That a branch is just a reference to a commit, and that the last commit of a branch is called its head. We also got to know a special reference, &lt;code&gt;HEAD&lt;/code&gt;, which points to a branch reference (which points to a commit) if we are currently on a branch, or a commit if we are in detached HEAD state.&lt;/p&gt;

&lt;p&gt;Here are some commands to remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git commit -am "my commit message"&lt;/code&gt; to commit all modified files without first staging them (does not work for untracked files)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git tag -a "my tag message"&lt;/code&gt; to create an annotated tag, for example if you're working with releases&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git push -u origin HEAD&lt;/code&gt; as an alternate way of doing &lt;code&gt;git push -u origin &amp;lt;my-branch-name&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Git blob and tree objects during the status lifecycle</title>
      <dc:creator>s-heins</dc:creator>
      <pubDate>Sat, 06 Nov 2021 21:30:55 +0000</pubDate>
      <link>https://forem.com/sheins/git-blob-and-tree-objects-during-the-status-lifecycle-1mmd</link>
      <guid>https://forem.com/sheins/git-blob-and-tree-objects-during-the-status-lifecycle-1mmd</guid>
      <description>&lt;p&gt;In order to find out what git does when we change files, we're going to create this directory and file hierarchy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── top-level-dir
│   ├── second-level-file.md
│   └── sub-level-dir
│       └── third-level-file.md
└── top-level-file.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To do so, we can run these commands in an empty git repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Lorem ipsum top level file"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; top-level-file.md
&lt;span class="nb"&gt;mkdir &lt;/span&gt;top-level-dir
&lt;span class="nb"&gt;cd &lt;/span&gt;top-level-dir
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Lorem ipsum second level file"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; second-level-file.md
&lt;span class="nb"&gt;mkdir &lt;/span&gt;sub-level-dir
&lt;span class="nb"&gt;cd &lt;/span&gt;sub-level-dir
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Lorem ipsum third level file"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; third-level-file.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Cover image by &lt;a href="https://freeimages.com/photographer/a_glitch-42001"&gt;wynand van niekerk&lt;/a&gt; from &lt;a href="https://freeimages.com"&gt;FreeImages&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Result after &lt;code&gt;add&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;After just running &lt;code&gt;git add .&lt;/code&gt;, &lt;strong&gt;not&lt;/strong&gt; commit, the contents of the &lt;code&gt;.git/objects&lt;/code&gt; folder now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree .git/objects

&lt;span class="nb"&gt;.&lt;/span&gt;
├── 1e
│   └── 86cd88d41dabd1342deb658da84a2bc9ab83cd
├── 51
│   └── 4ef3078e9106262d76be15bf23d83e8cd3bbe8
├── de
│   └── 8fcf5858a255ce7a9a60db7a004fa5b6ad80e5
├── info
└── pack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For every file, git has created a SHA-1 hash that is 40 characters long. The first two characters make up the name of the directory in the &lt;code&gt;.git/objects&lt;/code&gt; folder and the remaining 38 characters are used for the file name. To refer to an object, we don't always have to use the full 40-character hash; the first seven or so digits are usually sufficient for git to know which object we want since there is usually no other object sharing those first digits. In our example, our object hashes are &lt;code&gt;1e86cd8…&lt;/code&gt;, &lt;code&gt;514ef30…&lt;/code&gt;, and &lt;code&gt;de8fcf5…&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By examining the content with &lt;code&gt;git cat-file -p &amp;lt;object hash&amp;gt;&lt;/code&gt;, we can find out that &lt;code&gt;1e86cd8&lt;/code&gt; is the third-level file, &lt;code&gt;514ef30&lt;/code&gt; is the top-level file, and &lt;code&gt;de8fcf5&lt;/code&gt; is the second-level file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Insights
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;git already adds objects in the objects folder even if they are not committed&lt;/li&gt;
&lt;li&gt;apparently, it does not add &lt;code&gt;tree&lt;/code&gt; objects yet, just the blobs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Git will only add &lt;code&gt;tree&lt;/code&gt; objects after we commit our changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Result after &lt;code&gt;commit&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;After running &lt;code&gt;git commit&lt;/code&gt;, git has created a commit with the shortened hash &lt;code&gt;343d8dd&lt;/code&gt;.&lt;br&gt;
The git objects folder now looks like this (comments after &lt;code&gt;#&lt;/code&gt; sign):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree .git/objects

&lt;span class="nb"&gt;.&lt;/span&gt;
├── 1e
│   └── 86cd88d41dabd1342deb658da84a2bc9ab83cd   &lt;span class="c"&gt;# third-level-file.md&lt;/span&gt;
├── 34
│   └── 3d8dd527a9740dc15f8be4f5a8c71308b96926   &lt;span class="c"&gt;# new, commit object&lt;/span&gt;
├── 3a
│   └── 2e7f0d5abbe9b0d1bb26e6118f1c0070489e17   &lt;span class="c"&gt;# new&lt;/span&gt;
├── 4d
│   └── 9f43d4557e71eb6e5f540493ae5b92dfef7a67   &lt;span class="c"&gt;# new&lt;/span&gt;
├── 51
│   └── 4ef3078e9106262d76be15bf23d83e8cd3bbe8   &lt;span class="c"&gt;# top-level-file.md&lt;/span&gt;
├── a6
│   └── 9f01451a19e5ba5fce7c8bd1c584b9e2e711ed   &lt;span class="c"&gt;# new&lt;/span&gt;
├── de
│   └── 8fcf5858a255ce7a9a60db7a004fa5b6ad80e5   &lt;span class="c"&gt;# second-level-file.md&lt;/span&gt;
├── info
└── pack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking at information on the commit object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git cat-file &lt;span class="nt"&gt;-p&lt;/span&gt; 343d8dd

tree 4d9f43d4557e71eb6e5f540493ae5b92dfef7a67
author Sonja Heins &amp;lt;sonja.heins@example.com&amp;gt; 1636191282 +0100
committer Sonja Heins &amp;lt;sonja.heins@example.com&amp;gt; 1636191282 +0100

Add nested &lt;span class="nb"&gt;dirs &lt;/span&gt;and files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can look at all files and directories contained in the root tree &lt;code&gt;4d9f43d&lt;/code&gt; with the command &lt;code&gt;git ls-tree&lt;/code&gt; using the &lt;code&gt;-r&lt;/code&gt; flag for recursing into subtrees and the &lt;code&gt;-t&lt;/code&gt; flag for showing trees when recursing. I used &lt;code&gt;--abbrev=7&lt;/code&gt; here so git will abbreviate object hashes to seven digits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git ls-tree &lt;span class="nt"&gt;-rt&lt;/span&gt; 4d9f43d &lt;span class="nt"&gt;--abbrev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7

040000 tree a69f014 top-level-dir
100644 blob de8fcf5 top-level-dir/second-level-file.md
040000 tree 3a2e7f0 top-level-dir/sub-level-dir
100644 blob 1e86cd8 top-level-dir/sub-level-dir/third-level-file.md
100644 blob 514ef30 top-level-file.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we only want the files listed and not the tree objects, we can use &lt;code&gt;git ls-tree -r&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git ls-tree &lt;span class="nt"&gt;-r&lt;/span&gt; 4d9f43 &lt;span class="nt"&gt;--abbrev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7

100644 blob de8fcf5 top-level-dir/second-level-file.md
100644 blob 1e86cd8 top-level-dir/sub-level-dir/third-level-file.md
100644 blob 514ef30 top-level-file.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, after the first commit, our hierarchy is like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── commit 343d8dd 
│   └── tree 4d9f43d
│       ├── blob 514ef30            &lt;span class="o"&gt;(&lt;/span&gt;top-level-file.md&lt;span class="o"&gt;)&lt;/span&gt;
│       └── tree a69f014            &lt;span class="o"&gt;(&lt;/span&gt;top-level-dir&lt;span class="o"&gt;)&lt;/span&gt;
│            ├── blob de8fcf5       &lt;span class="o"&gt;(&lt;/span&gt;second-level-file.md&lt;span class="o"&gt;)&lt;/span&gt;
│            └── tree 3a2e7f0       &lt;span class="o"&gt;(&lt;/span&gt;sub-level-dir&lt;span class="o"&gt;)&lt;/span&gt;
│                └── blob 1e86cd8   &lt;span class="o"&gt;(&lt;/span&gt;third-level-file.md&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Changing a file
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Adding a line to the second-level file"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; top-level-dir/second-level-file.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have added a line to the second-level file. Before we run &lt;code&gt;git add&lt;/code&gt;, nothing changes in our object directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree .git/objects

&lt;span class="nb"&gt;.&lt;/span&gt;
├── 1e
│   └── 86cd88d41dabd1342deb658da84a2bc9ab83cd
├── 34
│   └── 3d8dd527a9740dc15f8be4f5a8c71308b96926
├── 3a
│   └── 2e7f0d5abbe9b0d1bb26e6118f1c0070489e17
├── 4d
│   └── 9f43d4557e71eb6e5f540493ae5b92dfef7a67
├── 51
│   └── 4ef3078e9106262d76be15bf23d83e8cd3bbe8
├── a6
│   └── 9f01451a19e5ba5fce7c8bd1c584b9e2e711ed
├── de
│   └── 8fcf5858a255ce7a9a60db7a004fa5b6ad80e5
├── info
└── pack

9 directories, 7 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After we run &lt;code&gt;git add .&lt;/code&gt;, we have a new directory and file, &lt;code&gt;f9cc8e0&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree .git/objects

&lt;span class="nb"&gt;.&lt;/span&gt;
├── 1e
│   └── 86cd88d41dabd1342deb658da84a2bc9ab83cd
├── 34
│   └── 3d8dd527a9740dc15f8be4f5a8c71308b96926
├── 3a
│   └── 2e7f0d5abbe9b0d1bb26e6118f1c0070489e17
├── 4d
│   └── 9f43d4557e71eb6e5f540493ae5b92dfef7a67
├── 51
│   └── 4ef3078e9106262d76be15bf23d83e8cd3bbe8
├── a6
│   └── 9f01451a19e5ba5fce7c8bd1c584b9e2e711ed
├── de
│   └── 8fcf5858a255ce7a9a60db7a004fa5b6ad80e5
├── f9
│   └── cc8e0b7374e973acbbc00c8742997ccd17d473   &lt;span class="c"&gt;# new&lt;/span&gt;
├── info
└── pack

10 directories, 8 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This object contains the new file changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git cat-file &lt;span class="nt"&gt;-p&lt;/span&gt; f9cc8e0

Lorem ipsum second level file
Adding a line to the second-level file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we commit and, in doing so, produce a new commit, &lt;code&gt;9d2aeae&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Add line to second-level-file.md"&lt;/span&gt;

&lt;span class="o"&gt;[&lt;/span&gt;main 9d2aeae] Add line to second-level-file.md
 1 file changed, 1 insertion&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Afterwards, our git object directory looks like this (comments after &lt;code&gt;#&lt;/code&gt; sign):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── 1e
│   └── 86cd88d41dabd1342deb658da84a2bc9ab83cd
├── 34
│   └── 3d8dd527a9740dc15f8be4f5a8c71308b96926
├── 3a
│   └── 2e7f0d5abbe9b0d1bb26e6118f1c0070489e17
├── 4d
│   └── 9f43d4557e71eb6e5f540493ae5b92dfef7a67
├── 51
│   └── 4ef3078e9106262d76be15bf23d83e8cd3bbe8
├── 9b
│   └── 676fbb2c624d1541263163ff84447242b5997b   &lt;span class="c"&gt;# new&lt;/span&gt;
├── 9d
│   └── 2aeae6478aa11d828bc4d969dbfc55186593bf   &lt;span class="c"&gt;# new (commit)&lt;/span&gt;
├── a0
│   └── 4ef2163c702bea83aa59d0fc5cc1547006b22f   &lt;span class="c"&gt;# new&lt;/span&gt;
├── a6
│   └── 9f01451a19e5ba5fce7c8bd1c584b9e2e711ed
├── de
│   └── 8fcf5858a255ce7a9a60db7a004fa5b6ad80e5
├── f9
│   └── cc8e0b7374e973acbbc00c8742997ccd17d473   &lt;span class="c"&gt;# changed second-level-file.md&lt;/span&gt;
├── info
└── pack

13 directories, 11 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to change our second-level-file, git needed to change the tree object for the top-level-dir folder as well as the root tree. After we committed our changes, git told us the new commit hash, &lt;code&gt;9d2aeae&lt;/code&gt;.&lt;br&gt;
We can now use this and run &lt;code&gt;git cat-file -p 9d2aeae&lt;/code&gt; to find out the hash for the root tree, &lt;code&gt;9b676fb&lt;/code&gt;.&lt;br&gt;
Let's run &lt;code&gt;ls-tree&lt;/code&gt; on this to see what it looks like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git ls-tree &lt;span class="nt"&gt;-rt&lt;/span&gt; 9b676fb &lt;span class="nt"&gt;--abbrev&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7

040000 tree a04ef21 top-level-dir
100644 blob f9cc8e0 top-level-dir/second-level-file.md
040000 tree 3a2e7f0 top-level-dir/sub-level-dir
100644 blob 1e86cd8 top-level-dir/sub-level-dir/third-level-file.md
100644 blob 514ef30 top-level-file.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, our hierarchy is like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── commit 343d8dd 
│   └── tree 4d9f43d
│       ├── blob 514ef30            &lt;span class="o"&gt;(&lt;/span&gt;top-level-file.md&lt;span class="o"&gt;)&lt;/span&gt;
│       └── tree a69f014            &lt;span class="o"&gt;(&lt;/span&gt;top-level-dir&lt;span class="o"&gt;)&lt;/span&gt;
│            ├── blob de8fcf5       &lt;span class="o"&gt;(&lt;/span&gt;second-level-file.md&lt;span class="o"&gt;)&lt;/span&gt;
│            └── tree 3a2e7f0       &lt;span class="o"&gt;(&lt;/span&gt;sub-level-dir&lt;span class="o"&gt;)&lt;/span&gt;
│                └── blob 1e86cd8   &lt;span class="o"&gt;(&lt;/span&gt;third-level-file.md&lt;span class="o"&gt;)&lt;/span&gt;
├── commit 9d2aeae 
│   └── tree 9b676fb
│       ├── blob 514ef30            &lt;span class="o"&gt;(&lt;/span&gt;top-level-file.md&lt;span class="o"&gt;)&lt;/span&gt;
│       └── tree a04ef21            &lt;span class="o"&gt;(&lt;/span&gt;top-level-dir&lt;span class="o"&gt;)&lt;/span&gt;
│            ├── blob f9cc8e0       &lt;span class="o"&gt;(&lt;/span&gt;second-level-file.md&lt;span class="o"&gt;)&lt;/span&gt;
│            └── tree 3a2e7f0       &lt;span class="o"&gt;(&lt;/span&gt;sub-level-dir&lt;span class="o"&gt;)&lt;/span&gt;
│                └── blob 1e86cd8   &lt;span class="o"&gt;(&lt;/span&gt;third-level-file.md&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The object hashes for top-level-file (&lt;code&gt;514ef30&lt;/code&gt;), sub-level-dir (&lt;code&gt;3a2e7f0&lt;/code&gt;), and third-level-file (&lt;code&gt;1e86cd8&lt;/code&gt;) have not changed, only the ones that lead us to second-level-file.md have changed, so the hash for the file itself and the ones for the trees that contain it.&lt;/p&gt;

</description>
      <category>git</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Branching and working with remotes in git</title>
      <dc:creator>s-heins</dc:creator>
      <pubDate>Fri, 22 Oct 2021 05:50:23 +0000</pubDate>
      <link>https://forem.com/sheins/branching-and-working-with-remotes-1a9k</link>
      <guid>https://forem.com/sheins/branching-and-working-with-remotes-1a9k</guid>
      <description>&lt;p&gt;In this article, we will have a look at how to work with remotes in order to work together with collaborators, how to work with branches, how to resolve conflicts between two sets of changes (aka "Why does git reject my push?"), and finally, how to merge and delete branches using the CLI or the GitHub UI.&lt;/p&gt;

&lt;p&gt;(Cover image by &lt;a href="https://freeimages.com/photographer/zirak-34282" rel="noopener noreferrer"&gt;fabrizio turco&lt;/a&gt; from &lt;a href="https://freeimages.com" rel="noopener noreferrer"&gt;FreeImages&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/sheins/-a-practical-introduction-to-git-jumping-in-with-both-feet-2o56"&gt;Introduction article&lt;/a&gt;, we looked at how to set up a local git repository, how to configure git and create aliases, and how to add and commit files on the example of creating an encyclopedia with articles and a list of topics to write about. We have also added some aliases to our gitconfig file at &lt;code&gt;~/.gitconfig&lt;/code&gt;, such as this one that lets us print a neat-looking tree in the command line to show us the git history. I'm adding it here again since we will keep using it throughout this article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
lg &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;clear &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git log &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'format:%C(auto)%h%d %s  %C(magenta)[%an] (%ad)%C(reset)'&lt;/span&gt; &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s1"&gt;'%d.%m.%y %H:%M'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we will look at how to save our work remotely so that we won't only have access to it locally on our machine but also on other machines and can work on changes together with collaborators. Our encyclopedia is going places and at any rate, we wouldn't want to do it all by ourselves. It's time to give this thing called balance a go and let other people join in on our project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Working with remotes
&lt;/h2&gt;

&lt;p&gt;All we have for now is our changes on our own machine. Anything that we commit will not be lost as long as our machine is working, but we can't share it with anyone else easily nor will it be safe if our device decides to stop working (as they tend to do in the most inopportune moments).&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a remote repository
&lt;/h3&gt;

&lt;p&gt;Firstly, we need to settle on a place to host our repository. This could be GitHub or GitLab, for example.&lt;br&gt;
After creating an account, we can create our repository.&lt;br&gt;
On how to set up a repository, please see these articles in their respective documentation pages: &lt;a href="https://docs.github.com/en/get-started/quickstart/create-a-repo" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://docs.gitlab.com/ee/user/project/repository/" rel="noopener noreferrer"&gt;GitLab&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Pushing our existing changes to the remote
&lt;/h3&gt;

&lt;p&gt;After creating a new repository on GitHub, it already shows us some instructions on how to push an existing git repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbzm33rbwdn9ar1u0ysl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbzm33rbwdn9ar1u0ysl.png" alt="GitHub instructions on how to push an existing repository"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first line is adding a so-called &lt;code&gt;origin&lt;/code&gt; to our local repository. This is referencing our new repo on github. In this example you can see that I have chosen to use SSH but this can be switched with a button further on top if you want to use HTTP. Using SSH will require you to set up a private and public SSH key pair whereas you will only have to authenticate with your username and password or access key if you use HTTP, so it will be easier if you have never done this before.&lt;br&gt;
Since I had previously connected to GitHub on my machine, I was not prompted for my login credentials here. If you are, enter the credentials you are prompted for and then you are able to push to your remote repository, to your origin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexiljbj6jndw9rk0vs1x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexiljbj6jndw9rk0vs1x.png" alt="Pushing to a remote repository"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After pushing, we can now see our changes on the site we have chosen as a host for our repo after refreshing in the browser. It will also show the last commit message, "Add a house cat" in this example, along with our files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feia07zdzfs44e8l3d7ps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feia07zdzfs44e8l3d7ps.png" alt="Github overview over repository"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Cloning a remote
&lt;/h3&gt;

&lt;p&gt;For now, we have worked alone on our encyclopedia, or rather, the list of animals we want to write about.&lt;br&gt;
Our git history will look something like this; it's a single line since we have only worked on one branch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fniksi4rudyb0xlbi38ny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fniksi4rudyb0xlbi38ny.png" alt="Git history with single branch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now our editor tells us to get cracking since so far, we have only made one measly list of animals to write about, it's not quite an encyclopedia. We have already pushed our repo, so we're ready to have collaborators join us in this project!&lt;br&gt;
We have managed to recruit Anna Animallover and Wolfgang Wanderlust to join us. Anna is going to help us complete our list of animals and then write articles on them and Wolfgang will write about cities of interest.&lt;/p&gt;

&lt;p&gt;You can find the address for your repository on the site you have chosen to host it – you will need this so that Anna and Wolfgang can clone your repository.\&lt;br&gt;
On GitHub, it looks like below. As before, you can choose either HTTP or SSH which will change the link. In this example, it is &lt;code&gt;https://github.com/s-heins/git-encyclopedia-example.git&lt;/code&gt; for HTTP and &lt;code&gt;git@github.com:s-heins/git-encyclopedia-example.git&lt;/code&gt; for SSH.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7ykc3i2e4dbc9wfdbeu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk7ykc3i2e4dbc9wfdbeu.png" alt="Github UI cloning repo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Anna and Wolfgang can then clone our repository by running &lt;code&gt;git clone &amp;lt;repository-address&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fif0xm2e4mif34zrw8vel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fif0xm2e4mif34zrw8vel.png" alt="Cloning the remote"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Branching
&lt;/h2&gt;

&lt;p&gt;The first thing Anna wants to do is create a new branch. This way we can keep the main branch for things that have already been reviewed and we can have our in-progress work in the other branches of our project.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating a new branch
&lt;/h3&gt;

&lt;p&gt;To create a new branch and switch to it, use &lt;code&gt;git checkout -b my-branch-name&lt;/code&gt;. In case you are working with tickets on Jira, for example, prefixing your branch with the ticket name enables your team to get a good overview on what tickets are currently in progress. We could name our branch "ENC-001_add-animal-articles" if our ticket number is "ENC-001", for example.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pushing a new branch to origin
&lt;/h3&gt;

&lt;p&gt;After Anna has added some articles (&lt;code&gt;git add .&lt;/code&gt;) and committed them to her local repository (&lt;code&gt;git commit -m "My message"&lt;/code&gt;), she wants to push those changes to the remote.&lt;br&gt;
She can do so by running &lt;code&gt;git push -u origin my-branch-name&lt;/code&gt;. With this, her local changes are propagated to our origin (also called &lt;em&gt;upstream&lt;/em&gt;), our repository on GitHub. Now it is possible for others to see Anna's changes and add their own.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh1com8n5xsg4pvkbrags.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh1com8n5xsg4pvkbrags.png" alt="Pushing a new branch to the remote"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From our machine, we can now &lt;code&gt;git pull&lt;/code&gt; and git will tell us that a new branch has been created. We can check it out by running &lt;code&gt;git checkout articles-on-animals-from-list&lt;/code&gt;. This will switch our working branch to Anna's branch and since we just pulled, we will also have her latest committed changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6dprtizf1e5yxii1zj97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6dprtizf1e5yxii1zj97.png" alt="Git pull shows me that a new branch has been created"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After we have created articles for the animals that are still missing from the list, we can add those changes to a commit and push them. This time, git already knows the upstream branch (namely, &lt;code&gt;origin/articles-on-animals-from-list&lt;/code&gt;), and thus we can just use &lt;code&gt;git push&lt;/code&gt; without any arguments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2yq1jq07ky86g2gxh3pm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2yq1jq07ky86g2gxh3pm.png" alt="Adding more files and pushing to the new branch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After Anna pulls again, she will also have our changes.&lt;/p&gt;

&lt;p&gt;By using the same branch and adding our commits, we can safely collaborate. Anna and me can both commit and push our changes as we go along. We just shouldn't both alter the same file at the same time or we will get conflicts that we will need to resolve.&lt;/p&gt;
&lt;h2&gt;
  
  
  Resolving conflicts
&lt;/h2&gt;

&lt;p&gt;Let's say we have the idea to add more animals to our list of animals to write about but Anna has the same idea. We add a gorilla and a chimpanzee, she adds an alligator and a crocodile. We push first so now the file will have updated without Anna knowing about it.&lt;/p&gt;

&lt;p&gt;When Anna tries to push her commit, git will not let her. It rejects her commit and tells her to pull first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgh7rmpzhx5qcmmq79gx2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgh7rmpzhx5qcmmq79gx2.png" alt="Git has rejected Anna's push"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once Anna pulls, git now tells her she has a conflict. If you use an IDE with version control functionality, you can also resolve any conflicts there and you normally would. Here, we will go the manual way for now because it will give us some insight into what happens in git behind the scenes without part of it being masked by IDE functionality.&lt;/p&gt;

&lt;p&gt;As you can see, the contents of the file have a line saying &lt;code&gt;HEAD&lt;/code&gt; that contain our changes where we added the gorilla and chimpanzee (the changes that we have already pushed to our branch on the remote), then another line of equals signs as separators, then her changes where she added the alligator and the crocodile, and then a line with the name of her commit, &lt;code&gt;7aaee11&lt;/code&gt;, and her commit message (&lt;code&gt;Add alligator and crocodile to the list&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpvt871rw9r3t5u3ac24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpvt871rw9r3t5u3ac24.png" alt="Git has rejected the pull since there were upstream changes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we look at the git tree in the console again, we can see that Anna's commit, &lt;code&gt;7aaee11&lt;/code&gt; and my commit that is pushed to the upstream, &lt;code&gt;ba9e8f3&lt;/code&gt; both have the same parent. We now have to resolve the conflicts so that Anna's changes can be propagated to our repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jdaup7c2o6ftzthzrrp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jdaup7c2o6ftzthzrrp.png" alt="Git tree with conflict"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can now edit the file to remove the three lines git has added to show us the parts of the file where we have conflicts. Since we want to retain all animals, we only need to delete these lines. As you can see on the screenshot, the file only has the list of animals afterwards, and the lines with the &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; and &lt;code&gt;====&lt;/code&gt; are no longer contained.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmyim51kzcbpgh2186lpb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmyim51kzcbpgh2186lpb.png" alt="Resolving conflicts"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After we have resolved the conflicts, we need to add the file so git knows that we can continue reconciling the changes that Anna and I have made.&lt;br&gt;
In this case, I have put a line in my &lt;code&gt;~/.gitconfig&lt;/code&gt; file telling git it should &lt;em&gt;rebase&lt;/em&gt; rather than try to &lt;em&gt;merge&lt;/em&gt; any conflicts. That means that it will try to make it as if Anna's changes had come after my own. We will go into the difference between merging and rebasing in a later article. For now, it doesn't matter that much which one you pick. If you look at the above screenshot, you will see git tells me to run &lt;code&gt;git rebase --continue&lt;/code&gt; once I am done resolving my conflicts. If you chose &lt;code&gt;merge&lt;/code&gt; as a pull strategy, it will tell you to run &lt;code&gt;git merge --continue&lt;/code&gt; instead. This will only have an impact on how our tree looks afterwards but it will not have any impact on our file changes.&lt;/p&gt;

&lt;p&gt;If we now look at the git tree after finishing the rebase, we can see that it looks as if Anna had done her changes after our own.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30gywqbpfvs0tv51464w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30gywqbpfvs0tv51464w.png" alt="If we look at the git tree, Anna's changes will appear after our own"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Merging and deleting branches from the console
&lt;/h2&gt;

&lt;p&gt;Let's say we have added articles on all animals we had on our list for now, have shown them to our editor, and they are happy with them. That means that we can now propagate those changes into our main branch and will no longer need our branch &lt;code&gt;articles-on-animals-from-list&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Firstly, we'll want to &lt;code&gt;git pull&lt;/code&gt; on our article branch to make sure we have the latest changes. Then, we check out the main branch and run &lt;code&gt;git merge articles-on-animals-from-list&lt;/code&gt;. Afterwards, we push again to make sure those changes are also on our upstream main branch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjusdz685c9u95fq8qsn0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjusdz685c9u95fq8qsn0.png" alt="Merging our branch to main"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Afterwards, we can delete the branch on your machine by running this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch &lt;span class="nt"&gt;-D&lt;/span&gt; articles-on-animals-from-list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this command to delete the remote branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;--delete&lt;/span&gt; articles-on-animals-from-list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Merging and deleting branches from the GitHub UI
&lt;/h2&gt;

&lt;p&gt;In practice, you will probably never run these commands from the CLI but rather use a version control provider such as GitHub or GitLab. Rather, you will create a request to propagate your changes into the main branch, called &lt;em&gt;pull request (PR)&lt;/em&gt; on GitHub, and &lt;em&gt;merge request (MR)&lt;/em&gt; on GitLab.&lt;/p&gt;

&lt;p&gt;On GitHub, click on the "Pull requests" tab and then on the button saying "Compare &amp;amp; pull request".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe475k2i4eop4aufpr94d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe475k2i4eop4aufpr94d.png" alt="Creating a pull request via the GitHub UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the next dialogue window, click on "Create pull request".&lt;br&gt;
You will see an overview page where you can see how many commits will be added to main and what changes they will introduce.&lt;/p&gt;

&lt;p&gt;After it has been reviewed, it can be merged to main by clicking the "Merge pull request" button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh3c0fheax13uvhtuhk8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh3c0fheax13uvhtuhk8w.png" alt="Click on "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After confirming the merge, you also have the option to delete your old branch via the UI. However, this will only delete the remote branch and you will still have to run &lt;code&gt;git branch -D articles-on-animals-from-list&lt;/code&gt; to delete your local branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and command summary
&lt;/h2&gt;

&lt;p&gt;We have looked at how to push our changes to a remote repository and have created our first branch, kept adding and committing and have resolved our first conflict!&lt;/p&gt;

&lt;p&gt;Here are some commands to keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git clone &amp;lt;address&amp;gt;&lt;/code&gt; to clone a remote repository&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git checkout -b my-branch-name&lt;/code&gt; to create a new branch and switch to it&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git push -u origin my-branch-name&lt;/code&gt; to push a branch to a remote&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git checkout my-branch-name&lt;/code&gt; to switch to an existing branch from the remote&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git pull&lt;/code&gt; to pull changes from the remote&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git rebase --continue&lt;/code&gt; or &lt;code&gt;git merge --continue&lt;/code&gt; to continue a rebase or merge after adding files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git merge my-branch&lt;/code&gt; to merge "my-branch" into the branch you have currently checked out&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git branch -D my-branch&lt;/code&gt; to delete "my-branch" locally&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git push --delete my-branch&lt;/code&gt; to delete "my-branch" on the upstream&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>A practical introduction to git – jumping in with both feet</title>
      <dc:creator>s-heins</dc:creator>
      <pubDate>Wed, 13 Oct 2021 20:08:06 +0000</pubDate>
      <link>https://forem.com/sheins/-a-practical-introduction-to-git-jumping-in-with-both-feet-2o56</link>
      <guid>https://forem.com/sheins/-a-practical-introduction-to-git-jumping-in-with-both-feet-2o56</guid>
      <description>&lt;p&gt;If you're a developer, you have probably heard about the version control system, git. If you haven't used it yourself yet, or not a lot, you might also be a bit scared by all the different words – commits, branches, pushing, cherry-picking, rebasing, … what is all that stuff? And why is version control so hard? What if I do the wrong thing and I end up losing everything?&lt;/p&gt;

&lt;p&gt;First up, git doesn't lose anything you have committed. It might be a bit harder to find but don't despair. We'll get you there.&lt;br&gt;
But let's start at the beginning without any looming threat of losing your changes.&lt;/p&gt;

&lt;p&gt;This will be the first article in a series and it will tell you how to set up your repository from the command line, how to add changes and save ("commit") them, how to set your name and email address to be added as metadata to those changes, and how to define a git aliases in general and a specific one to get a pretty git tree of your changes in the console.&lt;/p&gt;

&lt;p&gt;(Cover image by &lt;a href="https://freeimages.com/photographer/nexxy-42715" rel="noopener noreferrer"&gt;Nerry Burg&lt;/a&gt; from &lt;a href="https://freeimages.com" rel="noopener noreferrer"&gt;FreeImages&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;
  
  
  Why version control?
&lt;/h2&gt;

&lt;p&gt;If you add some files or change their contents, you'll want to have a way to save your progress. The difference between having the file in a version control system such as git rather than just saving it on your hard drive is that you have a history of the file along with additional metadata – you could revert back to an old version if you wanted to, look at exactly which changes were introduced when, by whom, and, if they wrote a meaningful message, why they did those changes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Your task
&lt;/h2&gt;

&lt;p&gt;Let's say you're tasked with creating an encyclopedia on animals. This is something that will require a lot of work, and re-working articles, so you want to know your articles are safe and sound. You might also want to revert some changes if your editor tells you to get rid of that article on flamingos one day and then changes their mind the next. You decide to start a git repository to commit your changes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Initializing your git repository
&lt;/h3&gt;

&lt;p&gt;In your shell, create a new directory and initialize your git repository by running &lt;code&gt;git init&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0g1y7tkm4u0ep37xg81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0g1y7tkm4u0ep37xg81.png" alt="Initializing a git repository"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, this creates to a hidden folder &lt;code&gt;.git&lt;/code&gt;. If we delete this folder again, your directory will no longer be a git repository.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configure
&lt;/h3&gt;

&lt;p&gt;So that other people know whom to contact regarding the changes you introduced because they might have some questions (or if you want to be able to run into some code and then marvel at the fact that these changes here were done by yourself a year ago and now you can't remember very much about them), you will want to set your name and email in your git config.&lt;br&gt;
You can either do so globally for the current logged-in user by running it with the &lt;code&gt;--global&lt;/code&gt; modifier which sets it for all repositories you commit to from this user on your machine, or for just this one repository if you run these commands with the &lt;code&gt;--local&lt;/code&gt; flag or leaving out the flag altogether since "local" is the default setting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &lt;span class="s2"&gt;"Evelyn Example"&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email evelyn@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Getting started on content
&lt;/h2&gt;

&lt;p&gt;Now that we've got this out of the way, let's get started!&lt;br&gt;
You might have noticed that git has automatically created a branch named "main" for us (or, depending on your settings, this may also be called "master". If you want to change the name of the default branch that gets created on running git init to something other than &lt;code&gt;master&lt;/code&gt;, you can run &lt;code&gt;git config --global init.defaultBranch main&lt;/code&gt; , or whichever name you prefer instead of &lt;code&gt;main&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Depending on which approach you are using when developing, you may work with additional branches, then creating merge requests that need to be approved so you can move these changes onto the main branch, or alternatively, just work with the main branch.&lt;br&gt;
Let's assume we're the only collaborator on this encyclopedia for now and thus, we can use the main branch to make our changes and will not run into trouble. (If multiple people are working on just one branch, it requires a team that is highly coordinated so those changes keep getting reviewed)&lt;/p&gt;
&lt;h3&gt;
  
  
  Adding files
&lt;/h3&gt;

&lt;p&gt;At first, we might want to create a list of animals we want to write articles on. We create a file &lt;code&gt;animals-to-write-about&lt;/code&gt; and add a line &lt;code&gt;house cat&lt;/code&gt; because, hey, everyone seems to be crazy about cats, so our encyclopedia needs to have an article on them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwbv1e4wcjaoj8nubuojk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwbv1e4wcjaoj8nubuojk.png" alt="Adding a new file to the git repository"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we want to know what the current status of our repository is, we can run &lt;code&gt;git status&lt;/code&gt;.&lt;br&gt;
Git says our file is an &lt;em&gt;untracked file&lt;/em&gt;… but what does that mean?&lt;/p&gt;

&lt;p&gt;If git does not yet know about a file, it is &lt;strong&gt;untracked&lt;/strong&gt;. If we want to add it to git, we can run &lt;code&gt;git add &amp;lt;file&amp;gt;&lt;/code&gt; or just add all files with &lt;code&gt;git add .&lt;/code&gt; (the dot at the end means all files in the current directory and sub-directories). In the next step, we can then &lt;code&gt;git commit&lt;/code&gt; these files. Only files that have been committed are safe from being lost, so we want to make sure we always commit any changes that we want to keep.&lt;br&gt;
By adding the &lt;code&gt;-m&lt;/code&gt; flag and then a note in quotation marks or single quotes, we can add a commit message. This should always start with an upper case verb in the present tense. For more pointers on how to write good commit messages, have a look at &lt;a href="https://chris.beams.io/posts/git-commit/" rel="noopener noreferrer"&gt;this article by Chris Beams&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cbt1mthzoh7v3q5vbwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7cbt1mthzoh7v3q5vbwg.png" alt="Creating our first commit"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Git aliases
&lt;/h3&gt;

&lt;p&gt;What was this &lt;code&gt;git lg&lt;/code&gt; command I just used to look at the changes? It was a git alias. This is a handy way to save all your typing energy for that encyclopedia.&lt;br&gt;
You can add your own aliases by editing the &lt;code&gt;~/.gitconfig&lt;/code&gt; file (on Linux / MacOS). My list looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# This is Git's per-user configuration file.&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;user]
    email &lt;span class="o"&gt;=&lt;/span&gt; s.heins@example.com
    name &lt;span class="o"&gt;=&lt;/span&gt; S Heins
&lt;span class="o"&gt;[&lt;/span&gt;credential]
    helper &lt;span class="o"&gt;=&lt;/span&gt; osxkeychain
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    s &lt;span class="o"&gt;=&lt;/span&gt; status
    c &lt;span class="o"&gt;=&lt;/span&gt; commit &lt;span class="nt"&gt;-m&lt;/span&gt;
    co &lt;span class="o"&gt;=&lt;/span&gt; checkout
    lg &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;clear &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git log &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'format:%C(auto)%h%d %s  %C(magenta)[%an] (%ad)%C(reset)'&lt;/span&gt; &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s1"&gt;'%d.%m.%y %H:%M'&lt;/span&gt;
    p &lt;span class="o"&gt;=&lt;/span&gt; pull &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;core]
    excludesfile &lt;span class="o"&gt;=&lt;/span&gt; /Users/heinss/.gitignore_global
&lt;span class="o"&gt;[&lt;/span&gt;commit]
    template &lt;span class="o"&gt;=&lt;/span&gt; /Users/heinss/.gitmessage.txt
&lt;span class="o"&gt;[&lt;/span&gt;pull]
    rebase &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;init]
    defaultBranch &lt;span class="o"&gt;=&lt;/span&gt; main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I highly recommend adding the alias under &lt;code&gt;lg&lt;/code&gt; for a pretty git tree right in your command line.&lt;/p&gt;

&lt;h2&gt;
  
  
  Outlook: Working with remotes and branches
&lt;/h2&gt;

&lt;p&gt;In the next article, we will be looking at how to work with remotes in case you want to save your work somewhere other than just your local machine and how to work with branches.&lt;/p&gt;

&lt;p&gt;If you work with multiple collaborators, working with branches in conjunction with a version control service such as github or gitlab that lets you create requests to propagate these changes into the main branch enables you to first review the changes before they go into your main branch most easily. Propagating changes from one branch to the other is called &lt;em&gt;merging&lt;/em&gt; one branch into the other.&lt;br&gt;
Otherwise, collaborators would commit in the main branch and if something goes seriously wrong, they would have to roll back those changes. Or if a commit needs to be reworked, additional rework commits need to be added, potentially bloating up your tree instead of the collaborator being able to still add them to their commit before merging. There are working modes though that use only one branch; this is called trunk-based development.&lt;br&gt;
However, most teams I have worked in have chosen to work with branching and so-called &lt;em&gt;merge requests&lt;/em&gt;, also called &lt;em&gt;pull requests&lt;/em&gt;.&lt;br&gt;
More on working with branches in the next post though!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and command summary
&lt;/h2&gt;

&lt;p&gt;We created our first local git repository, and added and committed a file to it!&lt;/p&gt;

&lt;p&gt;Here are some commands to keep in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git init&lt;/code&gt; to initialize a local git repository&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git status&lt;/code&gt; to show the current status of a repository and the files it contains&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git add .&lt;/code&gt; to add all files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git commit -m 'My message'&lt;/code&gt; to commit those changes with a commit message (i.e. propagate those changes to the branch and thus keep them from being lost)&lt;/li&gt;
&lt;li&gt;setting some options in the global git config file at &lt;code&gt;~/.gitconfig&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git config --global user.name "Evelyn Example"&lt;/code&gt; to set the author name globally (for all git repositories)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git config --global user.email evelyn@example.com&lt;/code&gt; to set the author email address globally&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git config --global init.defaultBranch main&lt;/code&gt; to set the default branch name when initializing a new repository to &lt;code&gt;main&lt;/code&gt; globally&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>git</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>codenewbie</category>
    </item>
  </channel>
</rss>
