<html>
<head>
  <title>Git 101</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/static/app.css">
<link rel="alternate" type="application/atom+xml" href="/atom.xml">
</head>
<body>
<header class="site-header">
  <div class="wrapper">
    <a class="site-title" href="/">Adam Neumann's blog</a>
    <nav class="site-nav">
      <input type="checkbox" id="nav-trigger" class="nav-trigger" />
      <label for="nav-trigger">
          <span class="menu-icon">
            <svg viewBox="0 0 18 15" width="18px" height="15px">
              <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
            </svg>
          </span>
      </label>
      <div class="trigger">
                <a class="page-link" href="/pages/about.html">About</a>
                <a class="page-link" href="/pages/resources.html">Resources</a>
              </div>
    </nav>
  </div>
</header>
<main class="page-content">
  <div class="wrapper">
    <article class="post">
      <header class="post-header">
        <h1 class="post-title">Git 101</h1>
        <p class="post-meta">
          <span>Aug 14, 2019</span>
        </p>
      </header>
      <div class="post-content">
        <h2>The problem: Git experience required</h2>
<p>One common situation I face when working with platform teams is the huge variation in the individuals' Git experience.
Git experience, although common for developers, is far less common for those with more traditional infrastructure or operations backgrounds.
And this makes sense, because source control has historically been used by software developers when they write code.
&quot;Configuration as code&quot; is still new.</p>
<p>The breakdown of experience tends to be something like this:</p>
<ul>
<li><strong>Some</strong> have used it a little and know enough to be dangerous</li>
<li><strong>A few</strong> are experts</li>
<li><strong>Most</strong> have not used it and are scared of it</li>
</ul>
<p>Often it is required to grow someone's Git knowledge from zero to &quot;highly functional in a collaborative team environment&quot;.
To make matters worse, this growth must happen in a short amount.
Even under ideal circumstances, Git is not an easy tool to learn.
Combine this with the existing cognitive load (from learning the numerous other new tools thrown their way) and the typical short duration project time pressures, and the result is an extremely poor learning environment.</p>
<h2>Git 101 - a simple, structured solution</h2>
<p>On a recent engagement, we tried a more formalized approach of teaching &quot;trunk-based development&quot; with Git in a simple way.
Although I had been doing this informally for a while, this time it was written on the whiteboard under the heading &quot;Git 101&quot;.</p>
<p>To put it simply:</p>
<blockquote>
<p>Git 101 provides <em>just enough Git</em> to enable a team of multiple engineers to work collaboratively on different streams of work and minimize distracting Git traps.</p>
</blockquote>
<p>This post is written for those who are already familiar with Git, but desire a focussed approach for teaching it in a short amount of time.</p>
<p>The best part of Git 101 is it can be tactile:</p>
<ul>
<li>you can write it down</li>
<li>they can write it down</li>
<li>you both can point at it as you do the steps</li>
<li>(most importantly) it will be there when you leave</li>
</ul>
<h2>Overview</h2>
<p>There are only 5 major commands.
2 are nearly identical.
They are executed roughly linearly.</p>
<ol>
<li><code>git pull</code></li>
<li><code>git add</code></li>
<li><code>git commit</code></li>
<li><code>git pull --rebase</code></li>
<li><code>git push</code></li>
</ol>
<h3>Some noteworthy omissions</h3>
<p>You may notice an absence of some informative (minor) commands like <code>git status</code>, <code>git log</code>, or <code>git diff</code>.
That is intentional.</p>
<p>There is an expectation that you will use these minor commands (when appropriate) in between each major step.
In addition to being useful commands in the own right, they are essential for explaining key concepts liked tracked/untracked files, staged/unchanged changes, and being ahead/behind of origin.</p>
<h2>Following the steps</h2>
<p>What I'd like to do next is run through the steps and expand upon each one.
I'm assuming you already have a remote repository cloned locally and you are working from <code>master</code> branch.</p>
<h3>1. <code>git pull</code></h3>
<p>Before making any changes, start off with a <code>git pull</code>.
This will make sure any new upstream changes are already in your local repository before making any commits.
This lessens the magnitude and likelihood of a conflict during the later <code>git pull --rebase</code>.</p>
<p>Now you do some work!</p>
<h3>2. <code>git add</code></h3>
<p>After finishing the work, run a <code>git add</code> to stage the important changes (emphasis on the <em>important</em>).
It may be tempting to stage all the changes with <code>git add .</code> or <code>git add -A</code> but I promise you this won't end well.
There will be pain, there will be tears.
Remember, this is Git 101.</p>
<p>Be explicit about exactly which changes will be added.</p>
<p>At a minimum, use <code>git add &lt;file_path&gt;</code> to stage everything in a file, and not <strong>everything</strong> in the directory tree.
I will start with this.</p>
<p>Ideally you will want to be even more explicit and use:</p>
<ul>
<li><code>git add -N &lt;new_file_path&gt;</code> to start tracking a new file excluding any file contents</li>
<li><code>git add -p</code> to perform hunk-by-hunk staging (in a very code review style)</li>
</ul>
<h3>3. <code>git commit</code></h3>
<p>Once the changes have been staged, it's time to make the commit.
Committing with <code>git commit -m &quot;&lt;message_goes_here&gt;&quot;</code> works great - giving the illusion of a one line command encourages brevity whilst avoiding a vi session, which can confuse some.</p>
<p>At first I won't focus too much on commit message content.
After a few iterations, I'll start to focus on it more.
Valuable commit messages <strong>add context</strong> to the commit content with information not contained within the commit itself.
For example, the message &quot;Added vars.yml&quot; adds no context, because that is easy to see in the commit.
Instead, focus on why this commit happened - was it related to something bigger, was it related to a story (with an ID), etc.</p>
<h3>4. <code>git pull --rebase</code></h3>
<p>Once the commit is ready, you are almost ready to push.
Almost.
Someone else has probably pushed a commit since you started work.
This is where <code>git pull --rebase</code> shines.</p>
<p>By running <code>git pull --rebase</code> next, you effectively:</p>
<ol>
<li>Take our new commit off the top of <code>master</code></li>
<li>Pull down any upstream changes</li>
<li>Put these upstream changes on top of master</li>
<li>Put our new commit on top of the inbound changes</li>
</ol>
<p>More succinctly, any upstream commits are placed in between your new commit and the previous commits.
A picture is worth a thousand words here, so draw one!</p>
<p>This adds a good amount of value.
This prevents any &quot;merge commits&quot; and keeps the commit history clean and linear.
This buys time to teach merging later on.
The worst thing that can happen is a conflict.
The best thing that can happen is nothing!</p>
<h3>5. <code>git push</code></h3>
<p>Now that your local repository is fully up to date with origin (or &quot;we have all the commits that are on BitBucket/Github&quot;) you can push the new commit.
This step is pretty straight forward.</p>
<p>Maybe this step fails because the rebase during <code>git pull --rebase</code> took some time, and someone else pushed to origin in the interim.
If this happens, just run another <code>git pull --rebase</code> and then try pushing again.</p>
<h2>Just a foundation</h2>
<p>That is it.
That is Git 101.
There are many commands you might want to <em>add</em>.
Critically though, there aren't any commands you can <em>remove</em> and preserve functionality.
Well, maybe the first <code>git pull</code>, but I think it's a valuable addition.</p>
<p>Now, you have a solid foundation to introduce more advanced concepts.
There are many directions you could go, such as introducing multiple commits and squashing, feature branches, WIP branches, Git implementation details, etc.
The point is, instead of leading with these concepts, you start with a simple foundation and iteratively add complexity.</p>
<p>Git 101 gives you a foundation to build upon, so that you can successfully introduce Git based source control to anyone.</p>

      </div>
    </article>
  </div>
</main>
<footer class="site-footer">
  <div class="wrapper">
    <div class="footer-col-wrapper">
      <div class="footer-col one-half">
        <h2 class="footer-heading">Adam Neumann's blog</h2>
        <ul class="contact-list">
          <li class="p-name">Adam Neumann</li>
          <li><a class="u-email" href="mailto:blog@noizwaves.com">blog@noizwaves.com</a></li>
        </ul>
      </div>

      <div class="footer-col one-half">
        <p>Technical blog of Adam Neumann. Engineer at Gusto in Boulder, CO.
        </p>
      </div>
    </div>
    <div class="footer-col-wrapper">
      <div class="social-links">
        <ul class="social-media-list">
          <li>
            <a href="https://github.com/noizwaves">
              <span class="username">Github</span>
            </a>
          </li>
          <li>
            <a href="https://www.twitter.com/noizwaves">
              <span class="username">Twitter</span>
            </a>
          </li>
        </ul>
      </div>
    </div>
  </div>
</footer>
</body>
</html>