<?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>DEV Community: Ben Sarrazin</title>
    <description>The latest articles on DEV Community by Ben Sarrazin (@bsrz).</description>
    <link>https://dev.to/bsrz</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%2F461721%2F1415ad89-9bf1-49f9-bafc-bc145795ddc7.png</url>
      <title>DEV Community: Ben Sarrazin</title>
      <link>https://dev.to/bsrz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bsrz"/>
    <language>en</language>
    <item>
      <title>Git Work Trees</title>
      <dc:creator>Ben Sarrazin</dc:creator>
      <pubDate>Wed, 01 Mar 2023 05:26:35 +0000</pubDate>
      <link>https://dev.to/bsrz/git-work-trees-fg9</link>
      <guid>https://dev.to/bsrz/git-work-trees-fg9</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://git-scm.com/docs/git-worktree" rel="noopener noreferrer"&gt;git worktree&lt;/a&gt; command allows you to use and/or manage multiple work trees at the same time.&lt;/p&gt;

&lt;p&gt;So what's a work tree? You're already using one, you just might not know it. Or you might call it "working copy".&lt;/p&gt;

&lt;p&gt;When you clone a repository the classic way (or create a new repository using &lt;code&gt;git init&lt;/code&gt;), git will create what is called the "main work tree":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;it clones the "bare" repository in the &lt;code&gt;.git&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;it creates the main work tree one level above the bare repository; what you might already know as simply "the folder in which the repository was cloned"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example:&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 clone git@github.com:bsrz/mvvm.git
Cloning into &lt;span class="s1"&gt;'mvvm'&lt;/span&gt;...
remote: Enumerating objects: 131, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;131/131&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;79/79&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Total 131 &lt;span class="o"&gt;(&lt;/span&gt;delta 56&lt;span class="o"&gt;)&lt;/span&gt;, reused 109 &lt;span class="o"&gt;(&lt;/span&gt;delta 38&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused 0
Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;131/131&lt;span class="o"&gt;)&lt;/span&gt;, 474.84 KiB | 2.53 MiB/s, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;56/56&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;mvvm
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
total 32
drwxr-xr-x  11 bsrz  staff    352 Feb 28 23:30 ./
drwxr-xr-x  25 bsrz  staff    800 Feb 28 23:30 ../
drwxr-xr-x  12 bsrz  staff    384 Feb 28 23:31 .git/
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1 bsrz  staff   2171 Feb 28 23:30 .gitignore
drwxr-xr-x   4 bsrz  staff    128 Feb 28 23:30 .img/
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1 bsrz  staff   1069 Feb 28 23:30 LICENSE
drwxr-xr-x   5 bsrz  staff    160 Feb 28 23:30 MVVM/
drwxr-xr-x   5 bsrz  staff    160 Feb 28 23:30 MVVM.xcodeproj/
drwxr-xr-x   4 bsrz  staff    128 Feb 28 23:30 MVVMTests/
drwxr-xr-x   4 bsrz  staff    128 Feb 28 23:30 MVVMUITests/
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1 bsrz  staff  22913 Feb 28 23:30 README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the &lt;code&gt;.git&lt;/code&gt; folder, and one level above (aka the current directory) contains all of the files committed to the repository, aka the work tree, or working copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;Ever had a situation where you had modified files and someone (maybe your boss) asked you to look into a bug in production code? Or maybe you have a major refactoring effort in progress with hundreds (or thousands!) of modified files, but you were asked to quickly complete another task?&lt;/p&gt;

&lt;p&gt;If so, then you'll be familiar with the Ill-just-commit-everything-I-have-in-a-WIP-commit approach or the stash management hell.&lt;/p&gt;

&lt;p&gt;Wouldn't it be a dream to have more than one branch checked out at the same time? This is why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Work trees
&lt;/h2&gt;

&lt;p&gt;Let's try out the same example as before but using work trees:&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;&lt;span class="nb"&gt;mkdir &lt;/span&gt;mvvm &lt;span class="c"&gt;# 1&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;mvvm &lt;span class="c"&gt;# 2&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git clone &lt;span class="nt"&gt;--bare&lt;/span&gt; git@github.com:bsrz/mvvm.git .bare &lt;span class="c"&gt;# 3&lt;/span&gt;
Cloning into bare repository &lt;span class="s1"&gt;'.bare'&lt;/span&gt;...
remote: Enumerating objects: 131, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;131/131&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;79/79&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Total 131 &lt;span class="o"&gt;(&lt;/span&gt;delta 56&lt;span class="o"&gt;)&lt;/span&gt;, reused 109 &lt;span class="o"&gt;(&lt;/span&gt;delta 38&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused 0
Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;131/131&lt;span class="o"&gt;)&lt;/span&gt;, 474.84 KiB | 2.43 MiB/s, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;56/56&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start by creating the directory that will contain all of your branches and the bare repository&lt;/li&gt;
&lt;li&gt;Change the directory to the newly created one&lt;/li&gt;
&lt;li&gt;This is the key part here, you want to clone a &lt;em&gt;bare&lt;/em&gt; version of the repository; this is more or less cloning only the &lt;code&gt;.git&lt;/code&gt; folder that's normally done automatically by the classic clone method&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next, you'll create the main work tree. This is done by using the &lt;code&gt;git worktree add&lt;/code&gt; method to register a new work tree with the bare 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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; .bare &lt;span class="c"&gt;# 1&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git worktree add ../main main &lt;span class="c"&gt;# 2&lt;/span&gt;
Preparing worktree &lt;span class="o"&gt;(&lt;/span&gt;checking out &lt;span class="s1"&gt;'main'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
HEAD is now at 0db2467 &amp;lt;commit message&amp;gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ../main &lt;span class="c"&gt;# 3&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; &lt;span class="c"&gt;# 4&lt;/span&gt;
total 36
drwxr-xr-x  11 bsrz  staff    352 Feb 28 23:53 ./
drwxr-xr-x   4 bsrz  staff    128 Feb 28 23:53 ../
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1 bsrz  staff     61 Feb 28 23:53 .git
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1 bsrz  staff   2171 Feb 28 23:53 .gitignore
drwxr-xr-x   4 bsrz  staff    128 Feb 28 23:53 .img/
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1 bsrz  staff   1069 Feb 28 23:53 LICENSE
drwxr-xr-x   5 bsrz  staff    160 Feb 28 23:53 MVVM/
drwxr-xr-x   5 bsrz  staff    160 Feb 28 23:53 MVVM.xcodeproj/
drwxr-xr-x   4 bsrz  staff    128 Feb 28 23:53 MVVMTests/
drwxr-xr-x   4 bsrz  staff    128 Feb 28 23:53 MVVMUITests/
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1 bsrz  staff  22913 Feb 28 23:53 README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Change the directory to the bare repository&lt;/li&gt;
&lt;li&gt;Add the main work tree to the mvvm folder, one level above the bare repository; 🗒️ this structure is purely a personal choice, you can clone the repository anywhere you want and check out branches anywhere you want&lt;/li&gt;
&lt;li&gt;Change the directory to your newly created work tree&lt;/li&gt;
&lt;li&gt;The committed files in your repository appear in the same way as before&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can work in the main directory in the exact same way as you were before. You can checkout other branches, you can stash modified files, you can commit files, you can rebase, merge, etc...&lt;/p&gt;

&lt;p&gt;The power of bare repositories lie in their ability to add a 2nd, a 3rd, an Nth work tree and checkout another branch inside of them.&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;&lt;span class="nb"&gt;cd&lt;/span&gt; ../.bare &lt;span class="c"&gt;# 1&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git worktree add &lt;span class="nt"&gt;--track&lt;/span&gt; ../my-awesome-branch &lt;span class="nt"&gt;-b&lt;/span&gt; my-awesome-branch &lt;span class="c"&gt;# 2&lt;/span&gt;
Preparing worktree &lt;span class="o"&gt;(&lt;/span&gt;new branch &lt;span class="s1"&gt;'my-awesome-branch'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
branch &lt;span class="s1"&gt;'my-awesome-branch'&lt;/span&gt; &lt;span class="nb"&gt;set &lt;/span&gt;up to track &lt;span class="s1"&gt;'main'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
HEAD is now at 0db2467 &amp;lt;commit message&amp;gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ../my-awesome-branch &lt;span class="c"&gt;# 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Go back to the bare repository&lt;/li&gt;
&lt;li&gt;Add a new work tree, this time we're creating a new branch and tracking it&lt;/li&gt;
&lt;li&gt;Change the directory to the new work tree&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now you can make modifications to the main work tree (using the main branch) &lt;em&gt;at the same time&lt;/em&gt; as making modifications to the my-awesome-branch work tree (using the my-awesome-branch branch). The same capabilities apply to the new work tree: you can checkout other branches, you can stash modified files, you can commit files, you can rebase, merge, etc...&lt;/p&gt;

&lt;p&gt;The only &lt;em&gt;caveat&lt;/em&gt; here, is that a branch can only be checked out in a single work tree at a time. If you try to checkout a branch that's already checked out in a different work tree, you will receive this error:&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 checkout main
fatal: &lt;span class="s1"&gt;'main'&lt;/span&gt; is already checked out at &lt;span class="s1"&gt;'/Users/bsrz/Developer/mvvm/main'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Although, I don't always use this method, I'm starting to use it more and more. The ability to leave my work in progress as is and start new work in a separate folder has given me a ton of flexibility and has caused a lot less "git management" work. I no longer have to constantly manage stashes or save patches for later, and it allows me to pivot onto a new problem pretty quickly.&lt;/p&gt;

&lt;p&gt;Hope this helped you learn something!&lt;br&gt;
Cheers! 🍻&lt;/p&gt;

</description>
      <category>aspdotnet</category>
      <category>vite</category>
      <category>softwaredevelopment</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
