<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Notes on Linux Maxxing dot com</title>
    <link>https://linuxmaxxing.com/notes/</link>
    <description>Recent content in Notes on Linux Maxxing dot com</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>No Copyright</copyright>
    <lastBuildDate>Sun, 02 Aug 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://linuxmaxxing.com/notes/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Git Notes</title>
      <link>https://linuxmaxxing.com/notes/git/</link>
      <pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://linuxmaxxing.com/notes/git/</guid>
      <description>&lt;div id=&#34;outline-container-headline-1&#34; class=&#34;outline-2&#34;&gt;&#xA;&lt;h2 id=&#34;headline-1&#34;&gt;&#xA;Git Repository&#xA;&lt;/h2&gt;&#xA;&lt;div id=&#34;outline-text-headline-1&#34; class=&#34;outline-text-2&#34;&gt;&#xA;&lt;div id=&#34;outline-container-headline-2&#34; class=&#34;outline-3&#34;&gt;&#xA;&lt;h3 id=&#34;headline-2&#34;&gt;&#xA;Concepts&#xA;&lt;/h3&gt;&#xA;&lt;div id=&#34;outline-text-headline-2&#34; class=&#34;outline-text-3&#34;&gt;&#xA;&lt;p&gt;File States&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;untracked&lt;/li&gt;&#xA;&lt;li&gt;staged&lt;/li&gt;&#xA;&lt;li&gt;committed&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Commit&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;snapshot of the repository at a given time&lt;/li&gt;&#xA;&lt;li&gt;it is not a diff&lt;/li&gt;&#xA;&lt;li&gt;diffs are calculated&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Commits are just a file&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;first two hash characters = the directory within &lt;code&gt;.git/objects&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;the rest is the filename&lt;/li&gt;&#xA;&lt;li&gt;this is to prevent inode busting from putting all commits under one directory&lt;/li&gt;&#xA;&lt;li&gt;commit stores entire history via pointers&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Hash&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;unique; depends on every aspect of the git operation:&lt;/p&gt;</description>
      <content:encoded><![CDATA[
<div id="outline-container-headline-1" class="outline-2">
<h2 id="headline-1">
Git Repository
</h2>
<div id="outline-text-headline-1" class="outline-text-2">
<div id="outline-container-headline-2" class="outline-3">
<h3 id="headline-2">
Concepts
</h3>
<div id="outline-text-headline-2" class="outline-text-3">
<p>File States</p>
<ol>
<li>untracked</li>
<li>staged</li>
<li>committed</li>
</ol>
<p>Commit</p>
<ul>
<li>snapshot of the repository at a given time</li>
<li>it is not a diff</li>
<li>diffs are calculated</li>
</ul>
<p>Commits are just a file</p>
<ul>
<li>first two hash characters = the directory within <code>.git/objects</code></li>
<li>the rest is the filename</li>
<li>this is to prevent inode busting from putting all commits under one directory</li>
<li>commit stores entire history via pointers</li>
</ul>
<p>Hash</p>
<ul>
<li>
<p>unique; depends on every aspect of the git operation:</p>
<ul>
<li>author name and email</li>
<li>commit</li>
<li>message</li>
<li>date and time</li>
<li>parent commit hashes</li>
</ul>
</li>
</ul>
<p>Git Objects</p>
<ul>
<li>git is made of up objects in the .git/objects directory</li>
<li>a commit is just one type of these objects</li>
<li>these objects will match commits shown in git log</li>
<li><code>cat</code> will show binary nonsense</li>
<li><code>git log</code> will output the object in hexadecimal format</li>
<li>git compresses files in the .git/objects directory</li>
<li>git deduplicates files common across commits</li>
<li>git does not change or overwrite past trees or blobs</li>
</ul>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git init                        <span class="c1"># create git repo in current directory</span>
</span></span><span class="line"><span class="cl">  git status                      <span class="c1"># see file states</span>
</span></span><span class="line"><span class="cl">  git add .                       <span class="c1"># does not recursively add</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git log
</span></span><span class="line"><span class="cl">  git --no-pager log
</span></span><span class="line"><span class="cl">  git --no-pager log -n <span class="m">10</span>    <span class="c1"># prints last 10 commits NOT in the pager (less)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># other options</span>
</span></span><span class="line"><span class="cl">  --oneline <span class="c1"># puts everything on one line</span>
</span></span><span class="line"><span class="cl">  --parents <span class="c1"># shows parent commmits</span>
</span></span><span class="line"><span class="cl">  --graph   <span class="c1"># shows commit/branch lines</span>
</span></span><span class="line"><span class="cl">  --all    <span class="c1"># shows all branches</span>
</span></span><span class="line"><span class="cl">  --decorate <span class="c1"># branch + tag info, can be short, full,no</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git log --decorate<span class="o">=</span>full</span></span></code></pre></div>
</div>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-3" class="outline-2">
<h2 id="headline-3">
git internals
</h2>
<div id="outline-text-headline-3" class="outline-text-2">
<ul>
<li>tree: git&#39;s way of storing a directory</li>
<li>blob: git&#39;s way of storing a file</li>
</ul>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  <span class="c1"># use the first 7 characters of the commit hash (4 might be sufficient)</span>
</span></span><span class="line"><span class="cl">  git cat-file -p &lt;commit hash&gt;   <span class="c1"># this will show the tree hash</span></span></span></code></pre></div>
</div>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git cat-file -p &lt;tree hash&gt;     <span class="c1"># this will show the blob hash</span></span></span></code></pre></div>
</div>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git cat-file -p &lt;blob&gt;          <span class="c1"># this will show the file hash</span></span></span></code></pre></div>
</div>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git cat-file -p &lt;file hash&gt;     <span class="c1"># shows contents of the file</span></span></span></code></pre></div>
</div>
</div>
</div>
<div id="outline-container-headline-4" class="outline-2">
<h2 id="headline-4">
git config
</h2>
<div id="outline-text-headline-4" class="outline-text-2">
<p>You can store any data you want in your git config files</p>
<ul>
<li>git might not use the data, but it can live there</li>
<li>use –global and –local flags after the operation</li>
<li>git config files can also be directly edited</li>
<li>git is case insensitive; defaultBranch and defaultbranch are the same</li>
</ul>
<p>Config files are located in the following places in reverse priority:</p>
<table>
<thead>
<tr>
<th>Location</th>
<th>Config File</th>
</tr>
</thead>
<tbody>
<tr>
<td>System</td>
<td><code>/etc/gitconfig</code></td>
</tr>
<tr>
<td>Global</td>
<td>~/.gitconfig</td>
</tr>
<tr>
<td>Local</td>
<td>.git/config</td>
</tr>
<tr>
<td>Worktree</td>
<td>.git/config.worktree</td>
</tr>
</tbody>
</table>
<p>
Local definitions will take priority over global definitions.</p>
<div id="outline-container-headline-5" class="outline-3">
<h3 id="headline-5">
git config set
</h3>
<div id="outline-text-headline-5" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git config <span class="nb">set</span> --global user.name <span class="s2">&#34;Bill S. Preston, Esq.&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># useless data for git, but allowed</span>
</span></span><span class="line"><span class="cl">  git config <span class="nb">set</span> --local organization.ceo <span class="s2">&#34;Ted&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># --add functionally does the same thing</span>
</span></span><span class="line"><span class="cl">  git config --add --global user.email <span class="s2">&#34;bill@email.com&#34;</span></span></span></code></pre></div>
</div>
</div>
</div>
<div id="outline-container-headline-6" class="outline-3">
<h3 id="headline-6">
git config list
</h3>
<div id="outline-text-headline-6" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git config list --local
</span></span><span class="line"><span class="cl">  git config list --global
</span></span><span class="line"><span class="cl">  cat .git/config                 <span class="c1"># local data</span>
</span></span><span class="line"><span class="cl">  cat ~/.gitconfig                <span class="c1"># global data</span></span></span></code></pre></div>
</div>
</div>
</div>
<div id="outline-container-headline-7" class="outline-3">
<h3 id="headline-7">
git config get
</h3>
<div id="outline-text-headline-7" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git config get &lt;key&gt;              <span class="c1"># &lt;key&gt; made up of section.value</span>
</span></span><span class="line"><span class="cl">  git config get user.name          <span class="c1"># section = user, value = name</span>
</span></span><span class="line"><span class="cl">  git config get --global user.name <span class="c1"># --global goes after get/set</span></span></span></code></pre></div>
</div>
</div>
</div>
<div id="outline-container-headline-8" class="outline-3">
<h3 id="headline-8">
git config unset
</h3>
<div id="outline-text-headline-8" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git config <span class="nb">unset</span> &lt;key&gt;           <span class="c1"># &lt;key&gt; needs a section and value</span>
</span></span><span class="line"><span class="cl">  git config <span class="nb">unset</span> --all &lt;section&gt; <span class="c1"># unset all of the same section</span>
</span></span><span class="line"><span class="cl">  git config <span class="nb">unset</span> user.name
</span></span><span class="line"><span class="cl">  git config <span class="nb">unset</span> user            <span class="c1"># THIS FAILS - needs a key and value</span></span></span></code></pre></div>
</div>
</div>
</div>
<div id="outline-container-headline-9" class="outline-3">
<h3 id="headline-9">
duplicates
</h3>
<div id="outline-text-headline-9" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  <span class="c1"># you can have multiples of a key</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># the last one is what is tracked in git</span>
</span></span><span class="line"><span class="cl">  git config <span class="nb">set</span> --append organization.ceo <span class="s2">&#34;Warren&#34;</span>
</span></span><span class="line"><span class="cl">  git config <span class="nb">set</span> --append organization.ceo <span class="s2">&#34;Carson&#34;</span>
</span></span><span class="line"><span class="cl">  git config <span class="nb">set</span> --append organization.ceo <span class="s2">&#34;Sarah&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># unset all of the same key</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># otherwise git will not allow unsetting that key</span>
</span></span><span class="line"><span class="cl">  git config <span class="nb">unset</span> --all &lt;key&gt;</span></span></code></pre></div>
</div>
</div>
</div>
<div id="outline-container-headline-10" class="outline-3">
<h3 id="headline-10">
Remove a section
</h3>
<div id="outline-text-headline-10" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git config remove-section &lt;section&gt;
</span></span><span class="line"><span class="cl">  git config remove-section user</span></span></code></pre></div>
</div>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-11" class="outline-2">
<h2 id="headline-11">
Branch
</h2>
<div id="outline-text-headline-11" class="outline-text-2">
<ul>
<li>Branch is a named pointer to a specific commit.</li>
<li>When you create 10 branches, you are not creating 10 copies of the project.</li>
</ul>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git branch                      <span class="c1"># shows you which branch you are on</span>
</span></span><span class="line"><span class="cl">  git branch -m oldname newname   <span class="c1"># rename</span>
</span></span><span class="line"><span class="cl">  git config <span class="nb">set</span> --global init.defaultBranch main</span></span></code></pre></div>
</div>
<div id="outline-container-headline-12" class="outline-3">
<h3 id="headline-12">
Create a  branch
</h3>
<div id="outline-text-headline-12" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git branch &lt;branchname&gt;
</span></span><span class="line"><span class="cl">  git switch -c &lt;branchname&gt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">#   Create a new branch off of a specific commit hash</span>
</span></span><span class="line"><span class="cl">  git switch -c &lt;branchname&gt; &lt;commit hash&gt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git checkout &lt;branchname&gt;          <span class="c1"># only works if &lt;branchname&gt; exits</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git branch -d &lt;branchname&gt;        <span class="c1"># delete branch</span>
</span></span><span class="line"><span class="cl">  git branch -D &lt;branchname&gt;        <span class="c1"># force delete a branch (unmerged commits)</span></span></span></code></pre></div>
</div>
<p>
When you create a branch:</p>
<ul>
<li>git uses the current commit you are on as the branch base</li>
<li>HEAD moves to that branch</li>
</ul>
<p>After deleting a branch</p>
<ul>
<li>The commits from that branch will no longer be visible in git log</li>
<li>Even with <code>git log --all</code>, you will no longer see any unmerged commits from that branch</li>
<li>Commits will still be visible in reflog</li>
</ul>
</div>
</div>
<div id="outline-container-headline-13" class="outline-3">
<h3 id="headline-13">
HEAD and tip
</h3>
<div id="outline-text-headline-13" class="outline-text-3">
<p>tip = most recent commit in a branch</p>
<p>
HEAD = commit you are working off of</p>
<p>
HEAD usually will be the tip, but does not necessarily have to be.</p>
<p>
The commit hash of HEAD of a branch is stored in <code>.git/refs/heads</code></p>
<p>
HEAD is stored in a file:</p>
<ul>
<li>.git/HEAD</li>
<li>This points to the branch HEAD stored in .git/refs/heads</li>
</ul>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-14" class="outline-2">
<h2 id="headline-14">
Merge
</h2>
<div id="outline-text-headline-14" class="outline-text-2">
<p>Typical Workflow</p>
<ul>
<li>Fetch or pull updated main branch</li>
<li>Create a branch to do stuff</li>
<li>Merge branch to main when sufficient via pull request or git merge on cli</li>
</ul>
<div id="outline-container-headline-15" class="outline-3">
<h3 id="headline-15">
Merge Commit
</h3>
<div id="outline-text-headline-15" class="outline-text-3">
<ul>
<li>Commit which merges two branches with diverging histories.</li>
<li>Only kind of commit with two parent commits.</li>
<li>Relative to Merge Base, aka best common ancestor</li>
</ul>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git merge &lt;feature_branch_name&gt;            <span class="c1"># usually done from main branch</span></span></span></code></pre></div>
</div>
</div>
</div>
<div id="outline-container-headline-16" class="outline-3">
<h3 id="headline-16">
Fast-forward merge
</h3>
<div id="outline-text-headline-16" class="outline-text-3">
<ul>
<li>Simplest</li>
<li>Tip of feature branch becomes the tip of main branch</li>
<li>NO MERGE COMMITS</li>
<li>Feature branch is merged into the main branch prior to additional main branch commits</li>
</ul>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-17" class="outline-2">
<h2 id="headline-17">
Rebase
</h2>
<div id="outline-text-headline-17" class="outline-text-2">
<p>Most misunderstood features of git</p>
<ul>
<li>Potential drawbacks for the unintiated:</li>
<li>e.g. someone changes the public history of a branch which screws up a ton of stuff</li>
</ul>
<p>Ideal scenario:</p>
<ul>
<li>You are working on a feature branch</li>
<li>There have been updates to main</li>
<li>You want to pull those updates from main onto your feature branch</li>
<li>After rebasing, this allows for a fast-forward merge</li>
</ul>
<p>Said otherwise</p>
<ul>
<li>Push the parent commit of the feature branch to the new tip of the main branch</li>
<li>The tip of the feature branch is now a fast-forward merge away from the main branch</li>
</ul>
<p>Allows maintaining a merge-commit-free history</p>
<ul>
<li>Has some benefits</li>
<li>Allows using certain git features if you maintain your history this way</li>
</ul>
<p>When on the feature branch, rebase with main</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git rebase main                <span class="c1"># from the feature branch</span></span></span></code></pre></div>
</div>
<hr>
<div id="outline-container-headline-18" class="outline-3">
<h3 id="headline-18">
WARNING: NEVER REBASE A PUBLIC BRANCH LIKE MAIN OR MASTER
</h3>
<div id="outline-text-headline-18" class="outline-text-3">
<ul>
<li>Out of habit, it is a good idea not to rebase your own private/fork main branches</li>
</ul>
<hr>
</div>
</div>
<div id="outline-container-headline-19" class="outline-3">
<h3 id="headline-19">
Rebase vs Merge
</h3>
<div id="outline-text-headline-19" class="outline-text-3">
<ul>
<li>Rebase will change commit hashes</li>
<li>
<p>Will have to address conflicts if rebasing:</p>
<ul>
<li>If there are conflicts in rebasing there would be conflicts in merging as well</li>
<li>Merging does not have any benefits over rebasing in this regard</li>
<li>Generally if there are no conflicts in a merge, there will be no conflicts in rebase</li>
</ul>
</li>
<li>
<p>Rebase advantage:</p>
<ul>
<li>Reverting commits</li>
<li>Only really done at scale</li>
</ul>
</li>
<li>
<p>Merge advantage:</p>
<ul>
<li>Shows true history</li>
</ul>
</li>
<li>
<p>Merge vs rebase might be enforced by some teams on the main branch</p>
<ul>
<li>For your own branches you can generally do whatever you want.</li>
</ul>
</li>
<li>
<p>An opinionated strategy:</p>
<ul>
<li>Always rebase</li>
<li>All merges then become fast-forward merges</li>
<li>If you are in a situation where you need to revert, it becomes really easy to do.</li>
<li>Squashing becomes easy</li>
</ul>
</li>
</ul>
<p>With merge conflict resolution</p>
<ul>
<li>
<p>you COMMIT the resolution</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git add &lt;file&gt;
</span></span><span class="line"><span class="cl">  git commit <span class="o">[</span>-m <span class="s2">&#34;Message&#34;</span><span class="o">]</span></span></span></code></pre></div>
</div>
</li>
</ul>
<p>With rebase conflict resolution</p>
<ul>
<li>
<p>you CONTINUE the resolution</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git rebase --continue</span></span></code></pre></div>
</div>
</li>
<li>you DO NOT commit rebase resolution</li>
</ul>
<p>If you happen to accidentally commit rebase resolutiton</p>
<ul>
<li>
<p>undo the commit</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git reset --soft HEAD~1</span></span></code></pre></div>
</div>
</li>
<li>then continue the rebase</li>
</ul>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-20" class="outline-2">
<h2 id="headline-20">
Undoing Changes
</h2>
<div id="outline-text-headline-20" class="outline-text-2">
<p>Git fundamentally does 3 things</p>
<ol>
<li>Add</li>
<li>Delete</li>
<li>Modify</li>
</ol>
<p>Conflicts arise on the modify portion</p>
<ul>
<li>If two commits edit the same line, git will throw a conflict</li>
<li>Requires personal editing and deconfliction</li>
<li>Comments in code can cause conflict</li>
</ul>
<div id="outline-container-headline-21" class="outline-3">
<h3 id="headline-21">
git reset –soft
</h3>
<div id="outline-text-headline-21" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git reset --soft &lt;commit hash&gt;
</span></span><span class="line"><span class="cl">  git reset --soft HEAD~1         <span class="c1"># go back one commit from HEAD</span></span></span></code></pre></div>
</div>
<ul>
<li>Undo the last commit and committed changes in the index (staged but not committed)</li>
<li>Commit changes will be uncommited and staged</li>
<li>Uncommited changes will remain staged or unstaged as before</li>
</ul>
</div>
</div>
<div id="outline-container-headline-22" class="outline-3">
<h3 id="headline-22">
git reset –hard
</h3>
<div id="outline-text-headline-22" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git reset --hard &lt;commit hash&gt;</span></span></code></pre></div>
</div>
<ul>
<li>Makes working directory and staging area match the last commit exactly</li>
<li>Disregards local changes</li>
</ul>
<hr>
<div id="outline-container-headline-23" class="outline-4">
<h4 id="headline-23">
DANGER: GIT RESET –HARD IS PERMANENT
</h4>
<div id="outline-text-headline-23" class="outline-text-4">
<ul>
<li>If we simply delete a commited/tracked file using <code>rm -rf filename</code>, we can easily restore</li>
<li>If we use hard reset prior to committing that file, those changes are gone for good</li>
<li>Still recoverable through reflog</li>
</ul>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-24" class="outline-3">
<h3 id="headline-24">
Change Commit Message
</h3>
<div id="outline-text-headline-24" class="outline-text-3">
<p>Rather than soft resetting to change a commit message, you can just do this:</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  <span class="c1"># this is a destructive item because it changes the commit hash</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># only do for latest commit which is not merged to main</span>
</span></span><span class="line"><span class="cl">  git commit --amend</span></span></code></pre></div>
</div>
<p>
This is a destructive operation and will change the commit hash.</p>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-25" class="outline-2">
<h2 id="headline-25">
Git Remote
</h2>
<div id="outline-text-headline-25" class="outline-text-2">
<p>
Remotes are just git repos</p>
<ul>
<li>We can have remotes that reside on our local machine.</li>
<li>Origin: If treating the remote as the authoritative source of truth, name it &#34;origin&#34;</li>
<li>
<p>Upstream:</p>
<ul>
<li>Sometimes this will be the authoritative.</li>
<li>Origin becomes what you&#39;re working in (fork of upstream).</li>
<li>You only want upstream when working with a lot of people and/or forking, etc.</li>
</ul>
</li>
</ul>
<div id="outline-container-headline-26" class="outline-3">
<h3 id="headline-26">
git fetch
</h3>
<div id="outline-text-headline-26" class="outline-text-3">
<ul>
<li>This fetches objects and bookeeping information about a repo into <code>.git/objects</code></li>
<li>It does not pull the files into your local branch(es).</li>
</ul>
</div>
</div>
<div id="outline-container-headline-27" class="outline-3">
<h3 id="headline-27">
Remote Commands
</h3>
<div id="outline-text-headline-27" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git remote add &lt;remote&gt; &lt;uri&gt;   <span class="c1"># notice this is uri, can be a file address</span>
</span></span><span class="line"><span class="cl">  git remote add origin ssh://git@forge.site/user/repo.git
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git ls-remote
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git push origin main            <span class="c1"># push the local main branch to origin</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># push a local branch to a remote branch of a differnet name</span>
</span></span><span class="line"><span class="cl">  git push origin &lt;localbranch&gt;:&lt;remotebranch&gt;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git push origin :&lt;remotebranch&gt; <span class="c1"># deletes a remote branch</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git log origin/master --oneline
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git merge &lt;remote&gt;/&lt;branchname&gt;
</span></span><span class="line"><span class="cl">  git merge origin/main           <span class="c1"># merge from the main branch on origin</span></span></span></code></pre></div>
</div>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-28" class="outline-2">
<h2 id="headline-28">
Git Pull
</h2>
<div id="outline-text-headline-28" class="outline-text-2">
<p>Pulls actual filechanges onto your local branch, not just metadata.</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  <span class="c1"># ensures we merge on a pull, may or may not want this</span>
</span></span><span class="line"><span class="cl">  git config <span class="nb">set</span> pull.rebase <span class="nb">false</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git pull origin main            <span class="c1"># pulls the main branch from origin</span></span></span></code></pre></div>
</div>
<p>
Workflow Example:</p>
<ul>
<li>Remote is truth</li>
<li>
<p>Rebase by default</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git config <span class="nb">set</span> --global pull.rebase true</span></span></code></pre></div>
</div>
</li>
</ul>
<p>Solo work:</p>
<ul>
<li>Everything on a single branch (main)</li>
</ul>
<p>Team work</p>
<ul>
<li>Work on new-branch</li>
<li>Push to origin new-branch</li>
<li>Open PR</li>
<li>Ask for review</li>
<li>After review, hit merge on remote forge</li>
<li>Delete new-branch merging</li>
</ul>
<hr>
<hr>
</div>
</div>
<div id="outline-container-headline-29" class="outline-2">
<h2 id="headline-29">
Gitignore
</h2>
<div id="outline-text-headline-29" class="outline-text-2">
<p>Example:
Adding <code>node-modules</code> to <code>.gitignore</code> will ignore every file that has exactly <code>node-modules</code> in its name.
It will not ignore files or directories that contain <code>node-modules-2</code></p>
<div id="outline-container-headline-30" class="outline-3">
<h3 id="headline-30">
Exclude file
</h3>
<div id="outline-text-headline-30" class="outline-text-3">
<p><code>.git/info/exclude</code></p>
<ul>
<li>Alternative to .gitignore</li>
<li>Allows your personal ignored files to not be part of the repo</li>
<li>Team members cannot see what kind of shady stuff you&#39;re hiding from the repo</li>
</ul>
</div>
</div>
<div id="outline-container-headline-31" class="outline-3">
<h3 id="headline-31">
Nested <code>.gitignore</code>
</h3>
<div id="outline-text-headline-31" class="outline-text-3">
<ul>
<li>.gitignore does not have to be a t the project root</li>
<li>There can be <code>.gitignore</code> in any directory of the project</li>
</ul>
</div>
</div>
<div id="outline-container-headline-32" class="outline-3">
<h3 id="headline-32">
Pattern Recognition
</h3>
<div id="outline-text-headline-32" class="outline-text-3">
<p>Patterns starting with a forward slash are anchored to that directory</p>
<ul>
<li>/main.py would ignore main.py in the root directory but not any other directories</li>
<li>&#34;*&#34; matches any number of characters except forward-slash</li>
<li>&#34;#&#34; comments</li>
<li>
<p>&#34;!&#34; indicates negation: negate specific files that would otherwise be ignored</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  ,*.txt
</span></span><span class="line"><span class="cl">  !/important.txt                 <span class="c1"># negates important.txt despite the *.txt wildcard</span></span></span></code></pre></div>
</div>
</li>
</ul>
<p>Order matters:</p>
<ul>
<li>one entry can override another</li>
<li>
<p>correct:</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  temp/*
</span></span><span class="line"><span class="cl">  !temp/instructions.md      <span class="c1"># this ignores all temp/ files except for instructions.md</span></span></span></code></pre></div>
</div>
</li>
<li>
<p>incorrect:</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  !temp/instructions.md
</span></span><span class="line"><span class="cl">  temp/*                          <span class="c1"># this overrides the above negation</span></span></span></code></pre></div>
</div>
</li>
</ul>
</div>
</div>
<div id="outline-container-headline-33" class="outline-3">
<h3 id="headline-33">
What to ignore:
</h3>
<div id="outline-text-headline-33" class="outline-text-3">
<p>Ignore things that can be generated or sensitive data</p>
<ul>
<li>compiled code</li>
<li>minified files</li>
<li>dependencies (e.g. node_modules, venv, packages, etc.)</li>
<li>personal or specific preferences (e.g. editor settings)</li>
<li>sensitive or dangerous things (e.g. .env files, passwords, API keys, etc.)</li>
</ul>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-34" class="outline-2">
<h2 id="headline-34">
Fork
</h2>
<div id="outline-text-headline-34" class="outline-text-2">
<ul>
<li>Not a git operation</li>
<li>Provided by git forges</li>
<li>Creates a copy of the original repo that you can edit</li>
</ul>
<div id="outline-container-headline-35" class="outline-3">
<h3 id="headline-35">
Why fork?
</h3>
<div id="outline-text-headline-35" class="outline-text-3">
<ul>
<li>Want to contribute to the project</li>
<li>
<p>Add second remote called upstream which points to original repo</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git remote add upstream &lt;uri&gt;</span></span></code></pre></div>
</div>
<ul>
<li>Can bring in latest changes to your fork</li>
</ul>
</li>
</ul>
</div>
</div>
<div id="outline-container-headline-36" class="outline-3">
<h3 id="headline-36">
PR tips
</h3>
<div id="outline-text-headline-36" class="outline-text-3">
<p>Review code on the actual git forge site</p>
<ul>
<li>Different look than your editor</li>
<li>Removes bias, potentially see stuff differently</li>
</ul>
<p>Make sure maintainers want these changes</p>
<ul>
<li>Look for issues</li>
<li>Consider creating an issue beforehand</li>
</ul>
</div>
</div>
<div id="outline-container-headline-37" class="outline-3">
<h3 id="headline-37">
Add yourself as a contributor
</h3>
<div id="outline-text-headline-37" class="outline-text-3">
<p>In the contributors/ directory, add:</p>
<ul>
<li>A file with your forge username.txt</li>
<li>A link to your forge profile in the text</li>
</ul>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-38" class="outline-2">
<h2 id="headline-38">
Reflog
</h2>
<div id="outline-text-headline-38" class="outline-text-2">
<table>
<thead>
<tr>
<th>Location</th>
<th>Descripion</th>
</tr>
</thead>
<tbody>
<tr>
<td>HEAD@{0}</td>
<td>where HEAD is now</td>
</tr>
<tr>
<td>HEAD@{1}</td>
<td>where HEAD was 1 move ago</td>
</tr>
<tr>
<td>HEAD@{2}</td>
<td>where HEAD was 2 moves ago</td>
</tr>
<tr>
<td>HEAD@{3}</td>
<td>where HEAD was 3 move ago</td>
</tr>
</tbody>
</table>
<ul>
<li>Reflog will show history of all operations, even destructive ones.</li>
<li>Can be used to restore after hard reset or long forgotten commits.</li>
<li>Records tip of branches and HEAD when updated; tracks every last step of HEAD.</li>
</ul>
<hr>
<div id="outline-container-headline-39" class="outline-3">
<h3 id="headline-39">
Restoring a deleted but previously committed file using git cat-file:
</h3>
<div id="outline-text-headline-39" class="outline-text-3">
<ul>
<li>Use git reflog to find the commit hash of the now deleted commit.</li>
<li>
<p>Use <code>git cat-file -p &lt;hash&gt;</code> to get the tree</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git cat-file -p &lt;commithash&gt;    <span class="c1"># gets the tree</span>
</span></span><span class="line"><span class="cl">  git cat-file -p &lt;tree&gt;          <span class="c1"># gets the blob</span>
</span></span><span class="line"><span class="cl">  git cat-file -p &lt;blob&gt;          <span class="c1"># gets the file-hash</span>
</span></span><span class="line"><span class="cl">  git cat-file -p &lt;file-hash&gt;     <span class="c1"># shows contents of file</span></span></span></code></pre></div>
</div>
</li>
</ul>
<hr>
</div>
</div>
<div id="outline-container-headline-40" class="outline-3">
<h3 id="headline-40">
Restoring a deleted file the fast way
</h3>
<div id="outline-text-headline-40" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  <span class="c1"># Instead of everything above, we could have just done:</span>
</span></span><span class="line"><span class="cl">  git merge HEAD@<span class="o">{</span>1<span class="o">}</span></span></span></code></pre></div>
</div>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-41" class="outline-2">
<h2 id="headline-41">
Conflicting Changes
</h2>
<div id="outline-text-headline-41" class="outline-text-2">
<ul>
<li>It is ok when the same line is modified in two separate commits</li>
<li>it Is not ok when the same line is modified in two commits with the same parent</li>
</ul>
<div id="outline-container-headline-42" class="outline-3">
<h3 id="headline-42">
Merge Conflicts
</h3>
<div id="outline-text-headline-42" class="outline-text-3">
<p>The TOP changes are OURS</p>
<ul>
<li>
<p>Should indicating HEAD (which is always local/ours)</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  <span class="o">&lt;&lt;&lt;&lt;&lt;&lt;</span>&lt;&lt; HEAD</span></span></code></pre></div>
</div>
</li>
</ul>
<p>The BOTTOM changes are THEIRS</p>
<ul>
<li>
<p>Should indicate the branch, e.g. main</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; main</span></span></code></pre></div>
</div>
</li>
</ul>
<p>You can manually accept both changes.</p>
<p>
To reset to a specific commit:</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git reset --hard &lt;commit hash&gt;</span></span></code></pre></div>
</div>
<hr>
</div>
</div>
<div id="outline-container-headline-43" class="outline-3">
<h3 id="headline-43">
Multi Conflict
</h3>
<div id="outline-text-headline-43" class="outline-text-3">
<p>The git checkout command can checkout the individual changes during a merge conflict using the –theirs or –ours flags.</p>
<ul>
<li>–ours keeps the version of the file from your current branch (the one you&#39;re on before merging)</li>
<li>–theirs uses the version of the file from the branch you&#39;re merging into your current branch</li>
</ul>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git checkout --theirs &lt;path/to/file&gt;
</span></span><span class="line"><span class="cl">  git checkout --ours &lt;path/to/file&gt;</span></span></code></pre></div>
</div>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-44" class="outline-2">
<h2 id="headline-44">
Rebase Conflicts
</h2>
<div id="outline-text-headline-44" class="outline-text-2">
<p>Most of the bad rap rebase gets is around conflicts because it rewrites history.</p>
<p>
Rarely will we have conflicts on our own stuff</p>
<p>
In the &#34;real world,&#34; what happens most often is:</p>
<ul>
<li>You switch to a new branch, say fix_bug, which is a copy of main.</li>
<li>While you&#39;re fixing the bug, someone else merges their changes into main.</li>
<li>You fix the bug, and it so happens that you edited the same files (and lines) that the other person did.</li>
<li>You open a Pull Request to merge (or rebase) fix_bug into main, then git tells you there&#39;s a conflict.</li>
<li>You resolve the conflict on your branch.</li>
<li>You complete the Pull Request with the conflict resolved.</li>
</ul>
<p>REMEMBER YOU SHOULD NEVER REBASE MAIN
MEANING YOU SHOULD NEVER TYPE THE WORDS:</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git rebase &lt;feature_branch&gt;     <span class="c1"># NEVER DO THIS</span></span></span></code></pre></div>
</div>
<p>
IF REBASING, YOU SHOULD ONLY TYPE:</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git rebase main                 <span class="c1"># rebase onto main</span>
</span></span><span class="line"><span class="cl">  git rebase master               <span class="c1"># rebase onto master</span></span></span></code></pre></div>
</div>
<p>
This is saying &#34;rebasing onto main/master.&#34;</p>
<div id="outline-container-headline-45" class="outline-3">
<h3 id="headline-45">
Detatched HEAD
</h3>
<div id="outline-text-headline-45" class="outline-text-3">
<p>After rebasing main on the feature branch and conflict arises:</p>
<ul>
<li>
<p>Check the branch</p>
<ul>
<li>YOU WILL NOT BE ON ANY BRANCH</li>
<li>your branch will be: (no branch, rebasing &lt;featurebranch&gt;)</li>
</ul>
</li>
<li>
<p>This is called detached HEAD</p>
<ul>
<li>temporary state</li>
<li>allows you to resolve the conflict before proceeding with the rebase</li>
</ul>
</li>
</ul>
</div>
</div>
<div id="outline-container-headline-46" class="outline-3">
<h3 id="headline-46">
Resolving Conflicts
</h3>
<div id="outline-text-headline-46" class="outline-text-3">
<p>Use git checkout –theirs and git checkout –ours
In a merge</p>
<ul>
<li>–ours refers to your current branch</li>
<li>
<p>this is most likely MAIN/MASTER</p>
<ul>
<li>sinced based bros will be rebasing onto a feature branch</li>
<li>and only (fast forward) merging onto main/master</li>
</ul>
</li>
</ul>
<p>In a rebase</p>
<ul>
<li>–ours refers to the branch you&#39;re rebasing onto.</li>
<li>in this case we are rebasing from the feature branch onto a different branch</li>
<li>it is probably main/master</li>
</ul>
<p>&#34;Accept current change&#34; is the same as</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git checkout --ours &lt;filepath&gt;</span></span></code></pre></div>
</div>
<ul>
<li>&lt;&lt;&lt;&lt;&lt;&lt;</li>
<li>top portion of the conflicting file</li>
</ul>
<p>&#34;Accept incoming change&#34; is the same as</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git checkout --theirs &lt;filepath&gt;</span></span></code></pre></div>
</div>
<ul>
<li>&gt;&gt;&gt;&gt;&gt;&gt;</li>
<li>bottom portion of the conflicting file</li>
</ul>
<div id="outline-container-headline-47" class="outline-4">
<h4 id="headline-47">
After resolving conflicts
</h4>
<div id="outline-text-headline-47" class="outline-text-4">
<p>Add the file.</p>
<p>
DO NOT COMMIT: YOU ARE STILL ON THE REBASE BRANCH</p>
<p>
Instead continue the rebase:</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git rebase --continue</span></span></code></pre></div>
</div>
<p>
Check the log</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git log --oneline --all</span></span></code></pre></div>
</div>
<p>
NOTE</p>
<ul>
<li>the commit we discarded is gone from git history</li>
<li>still accessible with reflog</li>
</ul>
<hr>
<hr>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-48" class="outline-2">
<h2 id="headline-48">
Repeat Resolution (rerere)
</h2>
<div id="outline-text-headline-48" class="outline-text-2">
<ul>
<li>&#34;Reuse recorded resolution&#34;</li>
<li>It allows you to ask Git to remember how you&#39;ve resolved a hunk conflict.</li>
<li>Next time it sees the same conflict, Git can resolve it for you automatically.</li>
<li>Applies to rebasing and merging</li>
</ul>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git config <span class="nb">set</span> --local rerere.enabled <span class="nb">true</span>
</span></span><span class="line"><span class="cl">  git config <span class="nb">set</span> --local rerere.enabled <span class="nb">false</span> <span class="c1"># disable rerere</span>
</span></span><span class="line"><span class="cl">  rm -rf .git/rr-cache            <span class="c1"># delete any remaining rerere cache</span></span></span></code></pre></div>
</div>
<div id="outline-container-headline-49" class="outline-3">
<h3 id="headline-49">
Conflict After Rebase Example:
</h3>
<div id="outline-text-headline-49" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  wagslane@MacBook-Pro-2 megacorp % git rebase main
</span></span><span class="line"><span class="cl">  Auto-merging customers/favs.md
</span></span><span class="line"><span class="cl">  CONFLICT <span class="o">(</span>add/add<span class="o">)</span>: Merge conflict in customers/favs.md
</span></span><span class="line"><span class="cl">  error: could not apply ad9b194... K
</span></span><span class="line"><span class="cl">  hint: Resolve all conflicts manually, mark them as resolved with
</span></span><span class="line"><span class="cl">  hint: <span class="s2">&#34;git add/rm &lt;conflicted_files&gt;&#34;</span>, <span class="k">then</span> run <span class="s2">&#34;git rebase --continue&#34;</span>.
</span></span><span class="line"><span class="cl">  hint: You can instead skip this commit: run <span class="s2">&#34;git rebase --skip&#34;</span>.
</span></span><span class="line"><span class="cl">  hint: To abort and get back to the state before <span class="s2">&#34;git rebase&#34;</span>, run <span class="s2">&#34;git rebase --abort&#34;</span>.
</span></span><span class="line"><span class="cl">  Recorded preimage <span class="k">for</span> <span class="s1">&#39;customers/favs.md&#39;</span> <span class="c1"># &lt;--- THIS LINE HERE</span>
</span></span><span class="line"><span class="cl">  Could not apply ad9b194... K</span></span></code></pre></div>
</div>
<p>
NOTICE:</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  Recorded preimage <span class="k">for</span> <span class="s1">&#39;customers/favs.md&#39;</span> <span class="c1"># &lt;--- THIS LINE HERE</span></span></span></code></pre></div>
</div>
<p>
Rerere is now recording how to resolve the conflict</p>
<ul>
<li>Either accept –ours (main) or –theirs (favs branch)</li>
<li>Or accept both by manually editing the file</li>
</ul>
<p>If we recreate the same conflict from another (third) branch (favs2)</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  wagslane@MacBook-Pro-2 megacorp % git rebase main
</span></span><span class="line"><span class="cl">  Auto-merging customers/favs.md
</span></span><span class="line"><span class="cl">  CONFLICT <span class="o">(</span>add/add<span class="o">)</span>: Merge conflict in customers/favs.md
</span></span><span class="line"><span class="cl">  error: could not apply ad9b194... K
</span></span><span class="line"><span class="cl">  hint: Resolve all conflicts manually, mark them as resolved with
</span></span><span class="line"><span class="cl">  hint: <span class="s2">&#34;git add/rm &lt;conflicted_files&gt;&#34;</span>, <span class="k">then</span> run <span class="s2">&#34;git rebase --continue&#34;</span>.
</span></span><span class="line"><span class="cl">  hint: You can instead skip this commit: run <span class="s2">&#34;git rebase --skip&#34;</span>.
</span></span><span class="line"><span class="cl">  hint: To abort and get back to the state before <span class="s2">&#34;git rebase&#34;</span>, run <span class="s2">&#34;git rebase --abort&#34;</span>.
</span></span><span class="line"><span class="cl">  Resolved <span class="s1">&#39;customers/favs.md&#39;</span> using previous resolution. <span class="c1"># &lt;--- THIS LINE HERE</span>
</span></span><span class="line"><span class="cl">  Could not apply ad9b194... K</span></span></code></pre></div>
</div>
<p>
NOTICE</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  Resolved <span class="s1">&#39;customers/favs.md&#39;</span> using previous resolution. <span class="c1"># &lt;--- THIS LINE HERE</span></span></span></code></pre></div>
</div>
<ul>
<li>if you open the conflicting file, the changes have already been made to match the first one</li>
</ul>
<p>Continue the rebase with</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git rebase --continue</span></span></code></pre></div>
</div>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-50" class="outline-2">
<h2 id="headline-50">
Squashing
</h2>
<div id="outline-text-headline-50" class="outline-text-2">
<p>Squashing groups a series of sequential, small commits into one commit. This is preferred by some teams</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git rebase -i HEAD~n            <span class="c1"># n is number of commits we want to squash</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># HEAD is current commit, ~n is n previous commits</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># -i creates an interactive rebase</span></span></span></code></pre></div>
</div>
<ol>
<li>
<p>git will open editor with a list of commits</p>
<ul>
<li>-i flag is interactive</li>
<li>Allows us to edit commit history</li>
</ul>
</li>
<li>
<p>Change the word &#34;pick&#34; to &#34;squash&#34; for all but the first commit</p>
<ul>
<li>First commit will be at the top of the editor prompt</li>
</ul>
</li>
<li>Save and close the editor</li>
</ol>
<hr>
<div id="outline-container-headline-51" class="outline-3">
<h3 id="headline-51">
Squashing Best practices
</h3>
<div id="outline-text-headline-51" class="outline-text-3">
<ol>
<li>
<p>Identify the main branch remote</p>
<ul>
<li>Might have to reset this</li>
<li>Most likely origin</li>
</ul>
</li>
<li>
<p>Create a temporary branch</p>
<ul>
<li>Rebase is destructive</li>
</ul>
</li>
<li>
<p>Perform the rebase on temp branch</p>
<ul>
<li>Emacs git-rebase-mode has its own keybindings; do not need to directly edit, just press &#34;s&#34; on all lines that should be changed from &#34;pick&#34; to &#34;squash&#34;</li>
</ul>
</li>
<li>
<p>Delete the main branch</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git branch -d main</span></span></code></pre></div>
</div>
</li>
<li>
<p>Rename temp branch to main</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git branch -m temp_main main</span></span></code></pre></div>
</div>
</li>
<li>
<p>Push and reset the main branch remote</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git push -u origin main
</span></span><span class="line"><span class="cl">  <span class="c1"># git might suggest:</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># git push --set-upstream origin main</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># which does the same thing</span></span></span></code></pre></div>
</div>
</li>
</ol>
<hr>
</div>
</div>
<div id="outline-container-headline-52" class="outline-3">
<h3 id="headline-52">
Force push
</h3>
<div id="outline-text-headline-52" class="outline-text-3">
<p>Force push required because this is a destructive operation on the remote main</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git push origin main --force</span></span></code></pre></div>
</div>
<p>
Your git history is rewritten, but full history is still accessible with reflog.</p>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-53" class="outline-2">
<h2 id="headline-53">
Stash
</h2>
<div id="outline-text-headline-53" class="outline-text-2">
<p>The git stash command:</p>
<ul>
<li>Records the current state of your working directory and the index (staging area).</li>
<li>Like your computer&#39;s copy/paste clipboard.</li>
<li>It records those changes in a safe place</li>
<li>Reverts the working directory to match the HEAD commit</li>
</ul>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git stash
</span></span><span class="line"><span class="cl">  git stash -m <span class="s2">&#34;jdsl v0 almost working&#34;</span> <span class="c1"># adds a message</span>
</span></span><span class="line"><span class="cl">  git stash list
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git stash pop                   <span class="c1"># applies the first stash on the stack</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># applies the first stash on the stack but keeps it in the stash list</span>
</span></span><span class="line"><span class="cl">  git stash apply
</span></span><span class="line"><span class="cl">  git stash apply stash@<span class="o">{</span>2<span class="o">}</span>       <span class="c1"># Apply the third (0, 1, 2) most recent stash</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git stash drop                  <span class="c1"># removes a stash without applying</span>
</span></span><span class="line"><span class="cl">  git stash drop stash@<span class="o">{</span>2<span class="o">}</span>        <span class="c1"># Remove the third most recent stash</span></span></span></code></pre></div>
</div>
<p>
The pop command will (by default):</p>
<ul>
<li>Apply your most recent stash entry to your working directory</li>
<li>Remove it from the stash list.</li>
<li>It effectively undoes the git stash command. It gets you back to where you were.</li>
</ul>
<div id="outline-container-headline-54" class="outline-3">
<h3 id="headline-54">
Stash is a Stack Data structure
</h3>
<div id="outline-text-headline-54" class="outline-text-3">
<p>The <code>git stash</code> command stores your changes in a stack (LIFO) data structure.
That means that when you retrieve your changes from the stash:</p>
<ul>
<li>You&#39;ll always get the most recent changes first.</li>
<li>Stores index and worktree.</li>
</ul>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-55" class="outline-2">
<h2 id="headline-55">
Revert
</h2>
<div id="outline-text-headline-55" class="outline-text-2">
<p>To revert a commit, you need to know the commit hash of the commit you want to revert (git log)</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git revert &lt;commit-hash&gt;</span></span></code></pre></div>
</div>
<div id="outline-container-headline-56" class="outline-3">
<h3 id="headline-56">
Revert vs Reset
</h3>
<div id="outline-text-headline-56" class="outline-text-3">
<p><code>git reset --soft</code>: Undo commits but keep changes staged</p>
<p>
<code>git reset --hard</code>: Undo commits and discard changes</p>
<p>
<code>git revert</code>: Create a new commit that undoes a previous commit</p>
<p>
When to Reset?:</p>
<ul>
<li>Working on your own branch,</li>
<li>Just undoing something you&#39;ve already committed,</li>
<li>E.g cleaning everything up so you can open a pull request</li>
</ul>
<p>When to Revert?:</p>
<ul>
<li>Undo a change that&#39;s already on a shared/public branch (especially if it&#39;s an older change)</li>
<li>It won&#39;t rewrite any history, and therefore won&#39;t step on your coworkers&#39; toes.</li>
</ul>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-57" class="outline-2">
<h2 id="headline-57">
Diff
</h2>
<div id="outline-text-headline-57" class="outline-text-2">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  <span class="c1"># show the changes between the working tree and the last commit</span>
</span></span><span class="line"><span class="cl">  git diff
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># show the differences between the previous commit and the current state, including the last commit and uncommitted changes</span>
</span></span><span class="line"><span class="cl">  git diff HEAD~1
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1"># show the change between two commits</span>
</span></span><span class="line"><span class="cl">  git diff COMMIT_HASH_1 COMMIT_HASH_2</span></span></code></pre></div>
</div>
<hr>
<hr>
</div>
</div>
<div id="outline-container-headline-58" class="outline-2">
<h2 id="headline-58">
Cherry-pick
</h2>
<div id="outline-text-headline-58" class="outline-text-2">
<p>Useful if you want one change from a branch but do not want the entire branch history.</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git cherry-pick &lt;commit-hash&gt;</span></span></code></pre></div>
</div>
<ul>
<li>You need a clean working tree (no uncommitted changes).</li>
<li>Identify the commit you want to cherry-pick, typically by git loging the branch it&#39;s on.</li>
</ul>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git cherry-pick &lt;commit-hash&gt;</span></span></code></pre></div>
</div>
<hr>
<hr>
</div>
</div>
<div id="outline-container-headline-59" class="outline-2">
<h2 id="headline-59">
Bisect
</h2>
<div id="outline-text-headline-59" class="outline-text-2">
<p>Git bisect is a binary search between known good and known bad commits.</p>
<ul>
<li>Finds the middle commit between a good and bad commit.</li>
<li>You check to see if that bug is present in that middle commit.</li>
<li>If not present, identify that commit as good. It then searches the middle of that and the bad commit.</li>
<li>Repeat until the bug is found.</li>
<li>Drastically cuts down time to find bugs.</li>
</ul>
<table>
<thead>
<tr>
<th class="align-right">Commits to Check</th>
<th class="align-right">Max Checks to Find</th>
</tr>
</thead>
<tbody>
<tr>
<td class="align-right">1</td>
<td class="align-right">1</td>
</tr>
<tr>
<td class="align-right">2</td>
<td class="align-right">1</td>
</tr>
<tr>
<td class="align-right">10</td>
<td class="align-right">4</td>
</tr>
<tr>
<td class="align-right">100</td>
<td class="align-right">7</td>
</tr>
<tr>
<td class="align-right">1000</td>
<td class="align-right">10</td>
</tr>
<tr>
<td class="align-right">10000</td>
<td class="align-right">14</td>
</tr>
</tbody>
</table>
<ol>
<li>
<p>Start the bisect with</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git bisect start</span></span></code></pre></div>
</div>
</li>
<li>
<p>Select a &#34;good&#34; commit with</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git bisect good &lt;commit hash&gt;     <span class="c1"># (a commit where you&#39;re sure the bug wasn&#39;t present)</span></span></span></code></pre></div>
</div>
</li>
<li>
<p>Select a &#34;bad&#34; commit with</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git bisect bad &lt;commit hash&gt;      <span class="c1"># (a commit where you&#39;re sure the bug was present)</span></span></span></code></pre></div>
</div>
</li>
<li>
<p>Git will checkout a commit between the good and bad commits. You must test to see if the bug is present in that commit.</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git show HEAD</span></span></code></pre></div>
</div>
</li>
<li>Execute <code>git bisect good</code> or <code>git bisect bad</code> to identify the current commit as good or bad.</li>
<li>Loop back to step 4 (until git bisect completes).</li>
<li>
<p>Exit the bisect mode with git bisect reset.</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git bisect reset</span></span></code></pre></div>
</div>
</li>
</ol>
<p>Then, take action to address the commit:</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  <span class="c1"># you want to revert the commit that introduced the bug - first &#34;bad commit&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># you do not want to revert the last good commit</span>
</span></span><span class="line"><span class="cl">  git revert &lt;bad_commit_hash&gt;</span></span></code></pre></div>
</div>
<p>
You can refer to commits as HEAD</p>
<ul>
<li>After the first bisect, you are really just saying HEAD is good or bad</li>
<li>
<p>For each iteration you simply manually check the file for the bug</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git show HASH
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  git show HEAD                   <span class="c1"># most likely</span></span></span></code></pre></div>
</div>
</li>
<li>
<p>git has no way of knowing what is the bug</p>
<ul>
<li>You don&#39;t &#34;tell&#34; git what the bug is and/or what to search for.</li>
<li>All git is doing is finding the middle commit.</li>
</ul>
</li>
</ul>
<hr>
<div id="outline-container-headline-60" class="outline-3">
<h3 id="headline-60">
Automating git bisect
</h3>
<div id="outline-text-headline-60" class="outline-text-3">
<p>From the git bisect man page:</p>
<blockquote>
<p>Bisect run
If you have a script that can tell if the current source code is good or bad, you can
bisect by issuing the command:</p>
<p>
$ git bisect run my_script arguments</p>
<p>
Note that the script (my_script in the above example) should exit with code 0 if the
current source code is good/old, and exit with a code between 1 and 127 (inclusive),
except 125, if the current source code is bad/new.</p>
</blockquote>
<p>
This could be accomplished by a script that:</p>
<ul>
<li>searches a file for whatever the problem is</li>
<li>returns 0 if the source is good</li>
<li>returns 1+ if the source is bad</li>
</ul>
<p>For example:</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  <span class="c1">#!/bin/sh</span>
</span></span><span class="line"><span class="cl">  <span class="c1"># bisect-script.sh</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> grep -q <span class="s2">&#34;SCANNING&#34;</span> <span class="s2">&#34;scripts/scan.sh&#34;</span><span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">      <span class="nb">exit</span> <span class="m">1</span>
</span></span><span class="line"><span class="cl">  <span class="k">else</span>
</span></span><span class="line"><span class="cl">      <span class="nb">exit</span> <span class="m">0</span>
</span></span><span class="line"><span class="cl">  <span class="k">fi</span></span></span></code></pre></div>
</div>
<ul>
<li>save and mark this script as executable somewhere in the repo</li>
<li>mark your good and bad initial commits</li>
</ul>
<p>Then run:</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git besect run ./bisect-script.sh</span></span></code></pre></div>
</div>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-61" class="outline-2">
<h2 id="headline-61">
Worktree
</h2>
<div id="outline-text-headline-61" class="outline-text-2">
<p>A worktree (or &#34;working tree&#34; or &#34;working directory&#34;):</p>
<ul>
<li>The directory on the local filesystem where code tracked in Git lives.</li>
<li>Usually just the root of your Git repo (where the .git directory is).</li>
<li>
<p>Contains:</p>
<ul>
<li>Tracked files - files that Git knows about</li>
<li>Untracked files - files that Git doesn&#39;t know about</li>
<li>Modified files - files that Git knows about that have been changed since the last commit</li>
</ul>
</li>
</ul>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git worktree list</span></span></code></pre></div>
</div>
<p>
Stash is still useful for small and short-lived changes.
Worktrees are better for long-lived changes.</p>
<p>
Worktrees accomplish a similar goal as stash, branch, clone, etc:</p>
<ul>
<li>Allow you to work on different changes without losing work.</li>
</ul>
<p>Linked worktrees but are particularly useful when you want to:</p>
<ul>
<li>Switch back and forth between the two change sets without having to run a bunch of git commands (not branches or stash).</li>
<li>Keep a light footprint on your machine that&#39;s still connected to the main repo (not a clone).</li>
</ul>
<div id="outline-container-headline-62" class="outline-4">
<h4 id="headline-62">
The Main Worktree
</h4>
<div id="outline-text-headline-62" class="outline-text-4">
<ul>
<li>Contains the .git directory with the entire state of the repo</li>
<li>Heavy (lots of data)</li>
<li>A new main working tree requires a git clone or git init.</li>
</ul>
</div>
</div>
<div id="outline-container-headline-63" class="outline-4">
<h4 id="headline-63">
Linked Worktree
</h4>
<div id="outline-text-headline-63" class="outline-text-4">
<ul>
<li>Contains a .git file with a path to the main working tree</li>
<li>Light (essentially no data), about as light as a branch.</li>
<li>Can be complicated to work with when it comes to env files and secrets.</li>
</ul>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git worktree add &lt;path&gt; &lt;branch&gt; <span class="c1"># create a new linked worktree</span></span></span></code></pre></div>
</div>
</div>
</div>
<div id="outline-container-headline-64" class="outline-3">
<h3 id="headline-64">
No Duplicate Branches
</h3>
<div id="outline-text-headline-64" class="outline-text-3">
<p>Linked worktrees behave just like a &#34;normal&#34; git repo. You can:</p>
<ul>
<li>create new branches</li>
<li>switch branches</li>
<li>delete branches</li>
<li>create tags</li>
<li>etc</li>
</ul>
<p>BUT there is one thing you cannot do:</p>
<ul>
<li>you cannot work on a branch that is currently checked out by any other working tree (main or linked worktree).</li>
</ul>
<p>Example: try to switch to main/master from a linked worktree.</p>
<ul>
<li>tldr; you can&#39;t</li>
</ul>
</div>
</div>
<div id="outline-container-headline-65" class="outline-3">
<h3 id="headline-65">
Upstream
</h3>
<div id="outline-text-headline-65" class="outline-text-3">
<p>Linked Worktrees are tracked in the <code>.git/worktrees</code> directory</p>
<p>
When you make a commit in a linked worktree, that commit is automatically reflected in the main worktree
Why this makes sense:</p>
<ul>
<li>The linked worktree doesn&#39;t have a .git directory</li>
<li>It is not a separate repository.</li>
<li>It is just a different view of the same repository.</li>
</ul>
<p>You can almost think of a linked worktree as just another branch in the same repo but with its own space on the filesystem.</p>
</div>
</div>
<div id="outline-container-headline-66" class="outline-3">
<h3 id="headline-66">
Delete Worktrees
</h3>
<div id="outline-text-headline-66" class="outline-text-3">
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git worktree remove &lt;worktree name&gt;</span></span></code></pre></div>
</div>
<p>
NOTE</p>
<ul>
<li>This deletes the worktree: it removes the worktree directory from the filesystem</li>
<li>It does not remove the branch.</li>
<li>Run <code>git branch</code> in the main git repo and you will see the branch without the &#34;+&#34; prefix which a worktree will have.</li>
</ul>
<p>Alternatively:</p>
<ul>
<li>Delete the worktree directory manually</li>
<li>
<p>Then prune all worktrees</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git worktree prune</span></span></code></pre></div>
</div>
</li>
</ul>
<hr>
<hr>
</div>
</div>
</div>
</div>
<div id="outline-container-headline-67" class="outline-2">
<h2 id="headline-67">
Tags
</h2>
<div id="outline-text-headline-67" class="outline-text-2">
<p>A tag is a name linked to a commit that does not move between commits, unlike a branch.</p>
<p>
Tags can be created and deleted, but not modified.</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git tag                         <span class="c1"># lists all tags</span>
</span></span><span class="line"><span class="cl">  git tag -a <span class="s2">&#34;tag name&#34;</span> -m <span class="s2">&#34;tag message&#34;</span> <span class="c1"># create a tag on the current commit</span></span></span></code></pre></div>
</div>
<div id="outline-container-headline-68" class="outline-3">
<h3 id="headline-68">
Semver -  Semantic Versioning
</h3>
<div id="outline-text-headline-68" class="outline-text-3">
<p>Naming convention for software - vMajor.Minor.Patch</p>
<ul>
<li>Major: breaking changes</li>
<li>Minor: safe features</li>
<li>Patch: safe bug fixes</li>
</ul>
<p>It has two primary purposes:</p>
<ol>
<li>To give us a standard convention for versioning software</li>
<li>To help us understand the impact of a version change: if it&#39;s safe (how hard it will be) to upgrade to</li>
</ol>
</div>
</div>
<div id="outline-container-headline-69" class="outline-3">
<h3 id="headline-69">
Conventional Tags
</h3>
<div id="outline-text-headline-69" class="outline-text-3">
<p>Tags are used for all sorts of reasons. Sometimes they&#39;re used to denote releases. Tags that follow semver are common.</p>
<div class="src src-shell">
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">  git tag -a v3.10.2 -m <span class="s2">&#34;Fixed a lil bug&#34;</span></span></span></code></pre></div>
</div>
</div>
</div>
</div>
</div>
]]></content:encoded>
    </item>
  </channel>
</rss>
