<?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: Ayush Poddar</title>
    <description>The latest articles on DEV Community by Ayush Poddar (@ello).</description>
    <link>https://dev.to/ello</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%2F634540%2Fee8a0293-df4d-4a95-8aa1-96b4d77fefd6.jpg</url>
      <title>DEV Community: Ayush Poddar</title>
      <link>https://dev.to/ello</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ello"/>
    <language>en</language>
    <item>
      <title>Practically evaluate your system's performance - Look beyond time complexity</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Fri, 10 May 2024 06:00:03 +0000</pubDate>
      <link>https://dev.to/ello/practically-evaluate-your-systems-performance-look-beyond-time-complexity-36gh</link>
      <guid>https://dev.to/ello/practically-evaluate-your-systems-performance-look-beyond-time-complexity-36gh</guid>
      <description>&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Time_complexity" rel="noopener noreferrer"&gt;Time complexity&lt;/a&gt; is a common parameter used to describe the performance of an algorithm. They tell us about the performance of an algorithm in terms of the size of the input. In other words, time complexity is a measure of the affect of input size on performance.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Consider an algorithm such as linear search on an unordered list of numbers &lt;em&gt;(linear time complexity)&lt;/em&gt;. The time taken by this algorithm increases linearly with the size of the input.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Time complexity is useful for a theoretical analysis on the performance of an algorithm. However, in the real world, our programs run on many layers of abstraction which introduce their own complexities and optimisations that are hard to account for in terms of mathematical equations or theoretical concepts.&lt;/p&gt;

&lt;p&gt;Real world data have special constraints which, in combination with the above-mentioned complexities and optimisations, may result in a theoretical worse algorithm to perform better. Apart from this, practically, we are often happy with good enough solutions that works for 99% of the cases in the real world. Many systems are built such that their accuracy is traded-off in favour of a performance boost.&lt;/p&gt;

&lt;p&gt;
  &lt;strong&gt;Example&lt;/strong&gt;
  &lt;p&gt;Most modern CPUs optimise the performance of our programs by pre-calculating the results of the operations that are yet to be executed in our coding programs. However, when these programs utilise conditionals &lt;em&gt;(like if-else statements)&lt;/em&gt;, there are chances of the pre-calculations occurring on the incorrect branch. This leads to a wastage of CPU cycles as the pre-calculations are performed on the wrong branch, affecting our systems’ performance.&lt;/p&gt;

&lt;/p&gt;

&lt;p&gt;The aim of this post is to encourage you to think beyond the time complexity calculations when evaluating your systems’ performance, and corroborate your knowledge of time complexity by benchmarking with real world data in the real world-like environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demonstration
&lt;/h2&gt;

&lt;p&gt;Consider this common leetcode problem: &lt;a href="https://leetcode.com/problems/climbing-stairs/description/" rel="noopener noreferrer"&gt;Climbing Stairs&lt;/a&gt;. The problem statement goes something like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There are &lt;code&gt;n&lt;/code&gt; steps in a staircase. You can take either 1, 2, or 3 steps at a time. In how many distinct ways can you climb the stairs?&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The solution to this problem is straight-forward. The aim of this post is not to discuss the correct solution but rather discuss the importance of evaluating the solution beyond the asymptotic analysis, i.e., the time and space complexity. The best solution to this problem has a linear time complexity and a constant space complexity. But I will be analysing the approach where the time complexity is in the order of 

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;(O(2n))(O(2^n)) &lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, since it will best demonstrate the importance of benchmarking by comparing similar algorithms with similar time complexity.&lt;/p&gt;
&lt;h3&gt;
  
  
  Building the solution(s)
&lt;/h3&gt;

&lt;p&gt;As an example consider a staircase with 5 steps &lt;code&gt;(n = 5)&lt;/code&gt;.&lt;/p&gt;


  &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd32g573a6sduc5.cloudfront.net%2Fimages%2Ffirst.png"&gt;"Stairing" into the abyss
  


&lt;p&gt;From the initial position, you can either go to &lt;strong&gt;step 1&lt;/strong&gt; or &lt;strong&gt;step 2&lt;/strong&gt; or &lt;strong&gt;step 3&lt;/strong&gt;.&lt;/p&gt;


  &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd32g573a6sduc5.cloudfront.net%2Fimages%2Ffirst-step.png"&gt;The first step (or leap)
  


&lt;p&gt;Essentially, now the problems breaks down into the sum of three sub-problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Number of ways you can get to &lt;strong&gt;step 5&lt;/strong&gt; from &lt;strong&gt;step 1&lt;/strong&gt;. &lt;em&gt;Or&lt;/em&gt;, the number of ways you can climb a 4-step staircase &lt;code&gt;(n = 4)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Number of ways you can get to &lt;strong&gt;step 5&lt;/strong&gt; from &lt;strong&gt;step 2&lt;/strong&gt;. &lt;em&gt;Or&lt;/em&gt;, the number of ways you can climb a 3-step staircase &lt;code&gt;(n = 3)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Number of ways you can get to &lt;strong&gt;step 5&lt;/strong&gt; from &lt;strong&gt;step 3&lt;/strong&gt;. &lt;em&gt;Or&lt;/em&gt;, the number of ways you can climb a 2-step staircase &lt;code&gt;(n = 2)&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mathematically speaking, if the function 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;f(n)f(n)&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;f&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is defined as the number of ways you can climb a staircase of 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;nn&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 steps, then:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;f(n)=f(n−1)+f(n−2)+f(n−3)
f(n) = f(n-1) + f(n-2) + f(n-3)
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;f&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;f&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;f&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;f&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;A straight-forward code implementation for the same is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;recursiveSolution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# When n = 0, 1, 2; return 1, 1, 2 respectively.
&lt;/span&gt;        &lt;span class="c1"&gt;# You can climb a 0 or 1 step staircase in only one way
&lt;/span&gt;        &lt;span class="c1"&gt;# and climb a 2-step staircase in 2 ways ((1, 1) and (2))
&lt;/span&gt;        &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;recursiveSolution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;recursiveSolution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;recursiveSolution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tree based approach
&lt;/h3&gt;

&lt;p&gt;Another way that this problem can be approached is by thinking in terms of a tree, where each node of the tree represents your current position on the staircase. There are three possible children from each node, one of every step you can take from your current position.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd32g573a6sduc5.cloudfront.net%2Fimages%2F2ivc7gxas8ngb9sd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd32g573a6sduc5.cloudfront.net%2Fimages%2F2ivc7gxas8ngb9sd.png"&gt;&lt;/a&gt;&lt;br&gt;The tree representation &lt;a href="https://d32g573a6sduc5.cloudfront.net/images/2ivc7gxas8ngb9sd.png" rel="noopener noreferrer"&gt;(Download)&lt;/a&gt;
  &lt;/p&gt;

&lt;p&gt;Next, you can find all the possible paths to the desired node (&lt;code&gt;position&lt;/code&gt;). Each node (&lt;code&gt;position&lt;/code&gt;) can be represented by a number, which represents your current position on the staircase. Initially, you start with &lt;code&gt;position = 0&lt;/code&gt; and you need to find all possible paths to &lt;code&gt;position = n&lt;/code&gt; (&lt;code&gt;position = 5&lt;/code&gt; in this case).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd32g573a6sduc5.cloudfront.net%2Fimages%2F5aowaiqgilxuwuad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd32g573a6sduc5.cloudfront.net%2Fimages%2F5aowaiqgilxuwuad.png"&gt;&lt;/a&gt;&lt;br&gt;Tree. Nodes represented as number
  &lt;/p&gt;

&lt;p&gt;This turns into a classic graph/tree problem, which you can solve either by performing a breadth-first search (BFS) or depth-first search (DFS). Implementing a depth-first search would basically replicate the recursive solution implemented earlier, with the only difference being that you would be manually managing the stack, instead of the program managing the stack in the form of call stack. The &lt;code&gt;python&lt;/code&gt; implementation of a DFS solution would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;deque&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;graphDFS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# start with position = 0
&lt;/span&gt;    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# get next position to evaluate
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# if current position is 0 or 1 or 2
&lt;/span&gt;            &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# just add to count
&lt;/span&gt;            &lt;span class="k"&gt;continue&lt;/span&gt;  &lt;span class="c1"&gt;# further evaluation not needed
&lt;/span&gt;        &lt;span class="c1"&gt;# Append the children to the stack
&lt;/span&gt;        &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The core logic of the &lt;code&gt;recursiveSolution&lt;/code&gt; function has been replicated as-it-is to ensure that both functions are as equivalent as possible. The breadth-first version of the solution would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;deque&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;graphBFS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# start with position = 0
&lt;/span&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;popleft&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# get next position to evaluate
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# if current position is 0 or 1 or 2
&lt;/span&gt;            &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# just add to count
&lt;/span&gt;            &lt;span class="k"&gt;continue&lt;/span&gt;  &lt;span class="c1"&gt;# further evaluation not needed
&lt;/span&gt;        &lt;span class="c1"&gt;# Push the children to the queue
&lt;/span&gt;        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two functions are the same except for the usage of stack in one and queue on another. The time complexity of all the three functions is 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;(O(2n))(O(2 ^n))&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This post assumes that you know how to calculate time complexity. Hence, it does not cover the calculation of the time complexity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Performance analysis
&lt;/h3&gt;

&lt;p&gt;To benchmark the performance of each of the above functions, I wrote a script that called each function from &lt;code&gt;n = 1&lt;/code&gt; to &lt;code&gt;n = 20&lt;/code&gt; and repeated this &lt;code&gt;x&lt;/code&gt; times (called &lt;code&gt;runs&lt;/code&gt;). Essentially, I wanted to find the total time taken by a function if it is called for all values between &lt;code&gt;n = 1&lt;/code&gt; and &lt;code&gt;n = 20&lt;/code&gt;. The script looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="c1"&gt;# Helper function to measure runtime
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;measure_runtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;end_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perf_counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;end_time&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;


&lt;span class="n"&gt;function_timings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;functions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;recursiveSolution&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;graphBFS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;graphDFS&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# to store the running times corresponding to each function
&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;  &lt;span class="c1"&gt;# number of times to repeat the benchmarking =&amp;gt; 10, 100, 1000, 10000
&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  &lt;span class="c1"&gt;# Test for n = 1 to n = 20
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
            &lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;time_taken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;measure_runtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;time_taken&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;# Average running time per run
&lt;/span&gt;    &lt;span class="n"&gt;function_timings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results shown below is the average execution time per “run”. In other words, each bar shows the total execution time for a function for all values of &lt;code&gt;n&lt;/code&gt; from 1 to 20.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd32g573a6sduc5.cloudfront.net%2Fimages%2Fo9ui46adm1ff4tgf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fd32g573a6sduc5.cloudfront.net%2Fimages%2Fo9ui46adm1ff4tgf.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As can be seen, clearly the &lt;code&gt;recursiveSolution&lt;/code&gt; function is the fastest. The next fastest function is the &lt;code&gt;graphBFS&lt;/code&gt; function, which is approximately &lt;strong&gt;~40%&lt;/strong&gt; slower than &lt;code&gt;recursiveSolution&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;
  &lt;strong&gt;Note&lt;/strong&gt;
  &lt;p&gt;I found it intriguing that &lt;code&gt;graphDFS&lt;/code&gt; is the slowest one (even if by a small margin). &lt;code&gt;graphDFS&lt;/code&gt; is fundamentally closer to &lt;code&gt;recursiveSolution&lt;/code&gt; since both of them use a stack to gather the results.&lt;/p&gt;

&lt;/p&gt;

&lt;h2&gt;
  
  
  Thoughts
&lt;/h2&gt;

&lt;p&gt;All the three functions have the same time complexity. All of them essentially implement the same logic. All of them return/continue when number of steps left is less than or equal to 2 (&lt;code&gt;&amp;lt;= 2&lt;/code&gt;). Yet, there is a &lt;strong&gt;~40%&lt;/strong&gt; difference in their performances.&lt;/p&gt;

&lt;p&gt;The analysis above aptly demonstrates that equivalent time complexity or algorithmic logic does not necessarily imply equivalent system performance. It is necessary to benchmark the functions/systems we implement to be able to accurately comment on their performance.&lt;/p&gt;

&lt;p&gt;However, it would be impractical to benchmark every bit of code we write. The decision on whether or not to benchmark is a judgement call that improves as we learn more about the hidden layers of abstraction in our systems. With knowledge and experience, we can make better judgement on whether or not we use time complexity as the sole metric to gauge the performance of our systems. &lt;em&gt;For example, in almost all cases, binary search would be better than linear search on a sorted list of numbers&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Best solution to this problem
&lt;/h2&gt;

&lt;p&gt;The solution to the &lt;a href="https://leetcode.com/problems/climbing-stairs/description/" rel="noopener noreferrer"&gt;Climbing Stairs&lt;/a&gt; problem that runs in linear time complexity is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;
  &lt;strong&gt;Note&lt;/strong&gt;
  &lt;p&gt;The solution is similar to the solution for getting the &lt;em&gt;nth&lt;/em&gt; number in the Fibonacci sequence.&lt;/p&gt;

&lt;/p&gt;

&lt;p&gt;I encourage you to try out different solutions (all of which execute in linear time complexity) and compare their performances. You can compare the above function with this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;linear2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;dp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think about more ways to achieve the same result in linear time complexity and compare their performances.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt; &lt;a href="https://csprimer.com/watch/staircase/" rel="noopener noreferrer"&gt;CS Primer - Staircase ascent problem&lt;/a&gt; → &lt;em&gt;I recommended this course for experienced software engineers who are looking to learn more about the foundational computer science concepts&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt; &lt;a href="https://csprimer.com/watch/analysis-practice/" rel="noopener noreferrer"&gt;CS Primer - Seminar on analysing systems&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Footnotes
&lt;/h2&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Leetcode presents a variant of this problem where you can take only 1 or 2 steps at a time. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>programming</category>
      <category>performance</category>
    </item>
    <item>
      <title>Magical Git when creating a branch off a remote branch</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Thu, 24 Aug 2023 19:20:25 +0000</pubDate>
      <link>https://dev.to/ello/magical-git-when-creating-a-branch-off-a-remote-branch-4gkm</link>
      <guid>https://dev.to/ello/magical-git-when-creating-a-branch-off-a-remote-branch-4gkm</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is part of my &lt;a href="https://poddarayush.com/shorts"&gt;"Shorts"&lt;/a&gt; series, where each post is concise and hyper-focused on a single concept.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Imagine that you clone a Git repository with many branches. After the clone is successful, if you run &lt;code&gt;git branch&lt;/code&gt;, you'd see that you only have the &lt;code&gt;main&lt;/code&gt; branch in your local repository. However, the command &lt;code&gt;git branch --all&lt;/code&gt; will output a list of branches prefixed by &lt;code&gt;remotes/origin/&lt;/code&gt;. Here is the top 5 lines of the output when running this command on the &lt;a href="https://github.com/discourse/discourse"&gt;discourse project&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* main
  remotes/origin/0-ansible-eggs
  remotes/origin/0-app-events-revolution
  remotes/origin/0-array-lint
  remotes/origin/0-assets-spec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assuming that you want to switch to the &lt;code&gt;0-ansible-eggs&lt;/code&gt; branch, you can run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout 0-ansible-eggs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have read my &lt;a href="https://dev.to/ello/did-you-know-a-git-branch-is-essentially-a-41-byte-file-4po2"&gt;earlier post on Git branches&lt;/a&gt;, you'd know that &lt;code&gt;git checkout&lt;/code&gt; can be used to switch to an existing branch, not to an non-existent branch. As already mentioned above, &lt;code&gt;0-ansible-eggs&lt;/code&gt; does not exist in your local repository.&lt;/p&gt;

&lt;p&gt;In this post, I will be exploring the magic that Git performs in making this short command work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Behind the scenes
&lt;/h2&gt;

&lt;p&gt;Assume that you want to switch to the &lt;code&gt;0-ansible-eggs&lt;/code&gt; (&lt;code&gt;remotes/origin/0-ansible-eggs&lt;/code&gt;) branch, but not with the same name. You may want to use a different name for the corresponding local branch, then the command that you'd use is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &amp;lt;localBranchName&amp;gt; remotes/origin/0-ansible-eggs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;localBranchName&lt;/code&gt; can be any name, even the same name you hated initially: &lt;code&gt;0-ansible-eggs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, when you run &lt;code&gt;git checkout 0-ansible-eggs&lt;/code&gt; and Git figures out that the branch &lt;code&gt;0-ansible-eggs&lt;/code&gt; does not exist &lt;em&gt;(it is not present in local)&lt;/em&gt; AND this branch is present in &lt;strong&gt;only one remote&lt;/strong&gt;, then Git will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Automatically create the local branch with the same name&lt;/li&gt;
&lt;li&gt;Set up tracking between the local branch and the remote branch&lt;/li&gt;
&lt;li&gt;Switch to the local branch&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In other words, Git expands &lt;code&gt;git checkout 0-ansible-eggs&lt;/code&gt; into &lt;code&gt;git checkout -b 0-ansible-eggs remotes/origin/0-ansible-eggs&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What did you learn in this post?
&lt;/h2&gt;

&lt;p&gt;You learned how the commonly used &lt;code&gt;git checkout&lt;/code&gt; command works behind the scenes even when the branch does not exist, in case of branches with the same name in remote.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Branching-Remote-Branches"&gt;https://git-scm.com/book/en/v2/Git-Branching-Remote-Branches&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>How to set a different Git branch name on remote</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Wed, 23 Aug 2023 19:54:40 +0000</pubDate>
      <link>https://dev.to/ello/how-to-set-a-different-git-branch-name-on-remote-3a17</link>
      <guid>https://dev.to/ello/how-to-set-a-different-git-branch-name-on-remote-3a17</guid>
      <description>&lt;p&gt;This post is part of my &lt;a href="https://poddarayush.com/shorts"&gt;"Shorts"&lt;/a&gt; series, where each post is concise and hyper-focused on a single concept.&lt;/p&gt;

&lt;p&gt;Some software development teams - who use project management tools like JIRA - enforce conventions like naming your branches after the ticket IDs &lt;em&gt;(e.g. &lt;code&gt;T-1234&lt;/code&gt;)&lt;/em&gt;. This practice helps create automated workflows and debugging. However, you might want a more descriptive branch name in your local development workflow &lt;em&gt;(e.g. &lt;code&gt;feat-user-auth&lt;/code&gt;)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In this post, we will be discussing how you can use different names for the same branch in your local and remote repositories.&lt;/p&gt;

&lt;h2&gt;
  
  
  How?
&lt;/h2&gt;

&lt;p&gt;When we run the command &lt;code&gt;git push origin branchName&lt;/code&gt;, under the hood, Git expands the command to &lt;code&gt;git push origin branchName:branchName&lt;/code&gt;. This expanded command means that the local branch named "branchName" should be pushed to remote branch named "branchName".&lt;/p&gt;

&lt;p&gt;So, using this as a hint, the way to use a different branch name in remote would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push origin localBranchName:remoteBranchName
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the context of our example, the command would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push origin feat-user-auth:T-1234
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You could also add the &lt;code&gt;--set-upstream&lt;/code&gt; flag to the command, so that you can directly run &lt;code&gt;git push&lt;/code&gt; next time when trying to push the changes in &lt;code&gt;feat-user-auth&lt;/code&gt; to its corresponding remote branch - &lt;code&gt;T-1234&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;When working in teams, having conventions for branch names is a very common practice. That does not mean that you should be losing your freedom to have your own custom branch names. Since now, you are in the position to have your own custom branch name while also following the conventions followed by your development team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Branching-Remote-Branches"&gt;https://git-scm.com/book/en/v2/Git-Branching-Remote-Branches&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Enhance the way you list Git branches with these 3 options</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Sun, 20 Aug 2023 17:44:59 +0000</pubDate>
      <link>https://dev.to/ello/enhance-the-way-you-list-git-branches-with-these-3-options-475i</link>
      <guid>https://dev.to/ello/enhance-the-way-you-list-git-branches-with-these-3-options-475i</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is part of my &lt;a href="https://poddarayush.com/shorts"&gt;"Shorts"&lt;/a&gt; series, where each post is concise and hyper-focused on a single concept.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a developer, you may already be aware of the &lt;code&gt;git branch&lt;/code&gt; command which is used to list all the branches in your repository. The sample output of a &lt;code&gt;git branch&lt;/code&gt; command looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* color-hidden-files
  main
  show-abs-path-xargs
  size-in-bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the asterisk (&lt;code&gt;*&lt;/code&gt;) sign represents the current branch, i.e., the branch that the &lt;a href="https://dev.to/ello/did-you-know-a-git-branch-is-essentially-a-41-byte-file-4po2"&gt;HEAD pointer&lt;/a&gt; points to.&lt;/p&gt;

&lt;p&gt;In this &lt;a href="https://poddarayush.com/shorts"&gt;short&lt;/a&gt; post, I intend to list some of the most used command line flags that can be used with the &lt;code&gt;git branch&lt;/code&gt; command. These flags will help you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;View the last commit in each branch&lt;/li&gt;
&lt;li&gt;List only merged/non-merged branches&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  View the last commit in each branch
&lt;/h2&gt;

&lt;p&gt;If you use the &lt;code&gt;--verbose&lt;/code&gt; (&lt;code&gt;-v&lt;/code&gt;) flag, you can view the last commit in each branch. The sample output of running &lt;code&gt;-v&lt;/code&gt; flag looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* color-hidden-files  305e248 refactor: split into two methods
  main                28c188b Merge pull request #594 from ayushpoddar/show-abs-path-xargs
  show-abs-path-xargs 44c370b Revert "version bump"
  size-in-bytes       5f3b880 spec fix: not more than 3 lines in the spec output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  List only merged branches
&lt;/h2&gt;

&lt;p&gt;If you want to see only those branches which have been merged into the current branch, then you need to use the &lt;code&gt;--merged&lt;/code&gt; command line flag. The output of running the command with the &lt;code&gt;--merged&lt;/code&gt; flag is similar to the output of a simple &lt;code&gt;git branch&lt;/code&gt; command. However, it filters out all the branches whose work is pending to be merged into the current branch.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can delete the branches whose commits have been merged into the current branch because the work done in those branches is available in the current branch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  List only non-merged branches
&lt;/h2&gt;

&lt;p&gt;Similar to above, if you want to list only those branches that have some commits which are not part of the current branch, then you can use the &lt;code&gt;--no-merged&lt;/code&gt; command line flag.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Branching-Branch-Management"&gt;https://git-scm.com/book/en/v2/Git-Branching-Branch-Management&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>When (and more importantly why) are merge commits created?</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Sat, 19 Aug 2023 20:25:43 +0000</pubDate>
      <link>https://dev.to/ello/when-and-more-importantly-why-are-merge-commits-created-430o</link>
      <guid>https://dev.to/ello/when-and-more-importantly-why-are-merge-commits-created-430o</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is part of my &lt;a href="https://poddarayush.com/shorts"&gt;"Shorts"&lt;/a&gt; series, where each post is concise and hyper-focused on a single concept.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you have worked with Git, you must have come across merge commits. These commits are not created every time you merge, but only on some special scenarios. In this post, we will learn about merge commits and when are they created. At the end of the post, I will also provide a way to avoid them.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, the simple fast-forward merge
&lt;/h2&gt;

&lt;p&gt;Consider that you have a branch named &lt;code&gt;featureX&lt;/code&gt; which diverges from the &lt;code&gt;main&lt;/code&gt; branch like shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3U-Q4dxh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mm3ljzsp0tx5hmbajkad.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3U-Q4dxh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mm3ljzsp0tx5hmbajkad.png" alt="" width="750" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you try to merge &lt;code&gt;featureX&lt;/code&gt; into &lt;code&gt;main&lt;/code&gt; using &lt;code&gt;git merge featureX&lt;/code&gt;, you will see the text &lt;code&gt;Fast-forward&lt;/code&gt; in the merge output. Git uses this merge strategy when the commit pointed to by the branch that is being merged into - &lt;code&gt;main&lt;/code&gt; in this case - is a direct ancestor of the branch that is being merged - &lt;code&gt;featureX&lt;/code&gt; in this case.&lt;/p&gt;

&lt;p&gt;In other words, if you start following the parent starting from the commit pointed to by &lt;code&gt;featureX&lt;/code&gt; and you reach the commit pointed to by &lt;code&gt;main&lt;/code&gt; after some jumps, Git will simply move &lt;em&gt;(fast-forward)&lt;/em&gt; the &lt;code&gt;main&lt;/code&gt; branch pointer to the commit pointed to by &lt;code&gt;featureX&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u_fSm3h6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbh4ouwz98hh0gs12y6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u_fSm3h6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbh4ouwz98hh0gs12y6z.png" alt="" width="750" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have used the &lt;code&gt;main&lt;/code&gt; branch as an example. I don't mean to convey that merges can only happen into the &lt;code&gt;main&lt;/code&gt; branch. Any Git branch can be merged into any Git branch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  When the main branch is NOT an ancestor of your feature branch
&lt;/h2&gt;

&lt;p&gt;Consider the scenario below where the &lt;code&gt;main&lt;/code&gt; branch has moved ahead from the point where &lt;code&gt;featureX&lt;/code&gt; diverged.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GjYl_l_Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jadn6kaapng3wpa85o0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GjYl_l_Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jadn6kaapng3wpa85o0e.png" alt="" width="750" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, the commit pointed to by &lt;code&gt;main&lt;/code&gt; is not an ancestor of the &lt;code&gt;featureX&lt;/code&gt; branch. So, Git tries to find the common ancestor of the &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;featureX&lt;/code&gt;. Then, Git performs a three-way merge between the common ancestor commit, the commit pointed to by &lt;code&gt;main&lt;/code&gt;, and the commit pointed to by &lt;code&gt;featureX&lt;/code&gt;. It creates a new snapshot that results from this merge and creates a "merge commit" on the &lt;code&gt;main&lt;/code&gt; branch &lt;em&gt;(or the branch being merged into)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0anL9RY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bozmfueooslbv1micepv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0anL9RY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bozmfueooslbv1micepv.png" alt="" width="750" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A merge commit has more than one parent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Avoiding merge commits
&lt;/h2&gt;

&lt;p&gt;To avoid "merge commits", you can rebase the &lt;code&gt;featureX&lt;/code&gt; branch on the &lt;code&gt;main&lt;/code&gt; branch. After the rebase, the commit pointed to by &lt;code&gt;main&lt;/code&gt; will become an ancestor of &lt;code&gt;featureX&lt;/code&gt;. To learn more about rebasing, I suggest you read my &lt;a href="https://dev.to/ello/stop-merging-the-main-branch-into-your-feature-branch-try-rebasing-5h87"&gt;post introducing git-rebase&lt;/a&gt;.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging"&gt;https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.git-init.com/the-magic-of-3-way-merge/"&gt;https://blog.git-init.com/the-magic-of-3-way-merge/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Did you know? A Git branch is essentially a 41-byte file</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Fri, 18 Aug 2023 18:57:23 +0000</pubDate>
      <link>https://dev.to/ello/did-you-know-a-git-branch-is-essentially-a-41-byte-file-4po2</link>
      <guid>https://dev.to/ello/did-you-know-a-git-branch-is-essentially-a-41-byte-file-4po2</guid>
      <description>&lt;p&gt;Any semi-experienced developer would have used Git branches as part of their development workflow. They are very important for effective collaboration and isolating under-development code from production code. Developers often use branches to try out new ideas, tools, etc and then delete the branch once done. You would agree with me when I say that working with branches in Git is a breeze, so much so that most of us take this feature for granted and never stop to think about the underlying implementation or appreciate its lightweightness.&lt;/p&gt;

&lt;p&gt;Most of us, who have never worked with any other &lt;a href="https://dev.to/ello/a-brief-history-of-git-or-version-control-systems-2oef"&gt;version control system&lt;/a&gt;, will not be able to appreciate the ease of working with branches in Git. Older version control systems like &lt;a href="https://subversion.apache.org/"&gt;Subversion&lt;/a&gt; usually took seconds or minutes (depending on the size of the repository) to create a new branch. On the other hand, creating a new branch in Git is almost instantaneous.&lt;/p&gt;

&lt;p&gt;In this post, I am going to explore the inner implementation of branching in Git and help you figure out: &lt;strong&gt;How are branches in Git so lightweight?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Branches as pointers
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/ello/internal-mechanics-of-git-commits-secret-to-gits-speed-and-lightweightness-1nk3"&gt;previous post&lt;/a&gt;, we learned that commits in Git are simple objects with a reference to the snapshot of the code at the time of commit and a reference to the parent (previous commit).&lt;/p&gt;

&lt;p&gt;Similarly, branches in Git are simple movable pointers that point to one of the commits. When you make a commit, the current branch's pointer automatically moves to the new commit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zt-PnT1x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k6sauvzdf9un2xrf0fx7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zt-PnT1x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k6sauvzdf9un2xrf0fx7.png" alt="" width="750" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There are no special properties associated with the &lt;code&gt;main&lt;/code&gt; branch. It is just another branch that is created by default by Git for you to start working on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Creating a new branch
&lt;/h2&gt;

&lt;p&gt;When you create a new branch, a new pointer is created that points to the last commit made in the current branch. The following command creates a new branch called &lt;code&gt;featureX&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch featureX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hifbO2hR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fv8wfhuberby6yj8gmec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hifbO2hR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fv8wfhuberby6yj8gmec.png" alt="" width="750" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  About HEAD
&lt;/h3&gt;

&lt;p&gt;To know which branch you are currently on, Git maintains a special pointer called &lt;code&gt;HEAD&lt;/code&gt;. It points to the current branch. In the figures above, you can see that &lt;code&gt;HEAD&lt;/code&gt; is pointing to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;git branch &amp;lt;branchName&amp;gt;&lt;/code&gt; only creates a new branch but does not switch to it. To switch to the new branch, in this case &lt;code&gt;featureX&lt;/code&gt;, you need to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout featureX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see in the figure below, switching to &lt;code&gt;featureX&lt;/code&gt; moved the &lt;code&gt;HEAD&lt;/code&gt; pointer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wydoCykO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/310vv4bg159xgi0287ub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wydoCykO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/310vv4bg159xgi0287ub.png" alt="" width="750" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can create and switch to a new branch in a single command:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; featureX
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What happens when you make a commit now?
&lt;/h2&gt;

&lt;p&gt;A new commit object is created and the &lt;code&gt;featureX&lt;/code&gt; branch pointer moves to the new commit, along with the &lt;code&gt;HEAD&lt;/code&gt; pointer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MQULNXJ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebv05cxu46in5cugl028.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MQULNXJ1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebv05cxu46in5cugl028.png" alt="" width="750" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Moving back to main
&lt;/h3&gt;

&lt;p&gt;If you move back to the &lt;code&gt;main&lt;/code&gt; branch now, the &lt;code&gt;HEAD&lt;/code&gt; pointer will again point to the &lt;code&gt;main&lt;/code&gt; branch, as shown below. Also, your files will be reverted to the snapshot that &lt;code&gt;main&lt;/code&gt; points to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VNKpohCs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sa77bw5ahv59blsrghbj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VNKpohCs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sa77bw5ahv59blsrghbj.png" alt="" width="750" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you make a new commit now, your project history will diverge. A new commit will be created which will be isolated from the commit you made in the &lt;code&gt;featureX&lt;/code&gt; branch. The figure below should help you get a better understanding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x6RG972G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tjdd2mducfzgv5qpg55e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x6RG972G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tjdd2mducfzgv5qpg55e.png" alt="" width="750" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Commits in both branches are isolated from each other. Switching to a branch will revert your files to the snapshot that the branch points to.&lt;/p&gt;

&lt;p&gt;As already mentioned in the &lt;a href="https://dev.to/ello/customise-how-you-view-your-git-commit-logs-with-these-options-3fkp"&gt;post about customizing git logs&lt;/a&gt;, you can view the divergent history of your repository using the &lt;code&gt;--graph&lt;/code&gt; flag.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;From Git version 2.23, Git has introduced the &lt;code&gt;switch&lt;/code&gt; subcommand which can be used to switch between branches.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To switch to a branch, run: &lt;code&gt;git switch &amp;lt;branchName&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To create and switch to a new branch: &lt;code&gt;git switch --create &amp;lt;branchName&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To return to the previously checked-out branch: &lt;code&gt;git switch -&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;A branch in Git is a simple file that contains the 40-character SHA-1 checksum of the commit it points to, making them extremely cheap and easy to create and destroy. Since we are recording the parent of commit, as &lt;a href="https://dev.to/ello/internal-mechanics-of-git-commits-secret-to-gits-speed-and-lightweightness-1nk3"&gt;mentioned in the previous post&lt;/a&gt;, Git can easily find the common merge base of two branches, making branches easy to use and merge.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Wondering how the git branch file is 41 bytes in size?&lt;/strong&gt; 40 bytes for the 40-character checksum and 1 byte for the newline.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell"&gt;https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Internal mechanics of Git commits - Secret to Git's speed and lightweightness</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Thu, 17 Aug 2023 13:33:47 +0000</pubDate>
      <link>https://dev.to/ello/internal-mechanics-of-git-commits-secret-to-gits-speed-and-lightweightness-1nk3</link>
      <guid>https://dev.to/ello/internal-mechanics-of-git-commits-secret-to-gits-speed-and-lightweightness-1nk3</guid>
      <description>&lt;p&gt;After a series of posts that focused on the practical usage of some of the Git concepts, this post, &lt;a href="https://dev.to/ello/how-does-git-store-the-version-history-of-a-project-36hn"&gt;once again&lt;/a&gt;, focuses on the internals of Git. I will tell you about the way Git works behind the scenes when we make a commit. This knowledge will help you understand why branching in Git is fast and extremely lightweight as compared to other version control systems, when we cover branching in a later post.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does Git store the commit internally?
&lt;/h2&gt;

&lt;p&gt;If you have read &lt;a href="https://dev.to/ello/how-does-git-store-the-version-history-of-a-project-36hn"&gt;my post covering the internals of Git storage&lt;/a&gt;, you'd know that Git stores the full snapshots of your files when they change and are committed. When you make a commit, a commit object is created by Git which contains a pointer to the previous commit(s) (&lt;code&gt;null&lt;/code&gt; in case of the first commit), a pointer to the snapshot of the content that has been committed, and metadata like the author's name, email and the commit message.&lt;/p&gt;

&lt;h3&gt;
  
  
  How is the snapshot created?
&lt;/h3&gt;

&lt;p&gt;Assume that your repository's directory structure looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dir-1/
|-- 1-bar.txt
|-- 1-foo.txt
`-- dir-2/
    `-- 2-foo.txt

1 directory, 3 files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assuming that all the files are modified and staged, Git first computes the checksum (SHA1 hash) of each file and stores those checksums as &lt;strong&gt;blobs&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;file&lt;/th&gt;
&lt;th&gt;blob checksum&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dir-1/1-bar.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;da39a3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dir-1/1-foo.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1eaf2e&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dir-1/dir-2/2-foo.txt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;5f2a25&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;You can run &lt;code&gt;shasum &amp;lt;filename&amp;gt;&lt;/code&gt; to calculate the SHA1 checksum of a file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, Git calculates the checksum of each subdirectory &lt;em&gt;(essentially the checksum of all blobs in the subdirectory)&lt;/em&gt; and stores them as &lt;strong&gt;trees&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So, the "tree" for &lt;code&gt;dir-1/dir-2&lt;/code&gt; contains the blob checksum of &lt;code&gt;dir-1/dir-2/2-foo.txt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HvxyfXxO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/16kw4iywcgg6qzpnu2n5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HvxyfXxO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/16kw4iywcgg6qzpnu2n5.png" alt="" width="450" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The "tree" for &lt;code&gt;dir-1&lt;/code&gt; contains the blob checksums of &lt;code&gt;1-bar.txt&lt;/code&gt; and &lt;code&gt;1-foo.txt&lt;/code&gt;, in addition to the tree checksum of &lt;code&gt;dir-2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NcZdL4Z_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/agj2pwe6ecxx0i18kyhv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NcZdL4Z_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/agj2pwe6ecxx0i18kyhv.png" alt="This is the final snapshot" width="700" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To get the SHA1 checksum of a directory, you can run&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;shasum &amp;lt;file1&amp;gt; &amp;lt;file2&amp;gt; .. &amp;lt;fileN&amp;gt; | shasum
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;where &lt;code&gt;file&lt;/code&gt; is a file inside the directory and its subdirectories.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Storage of commit
&lt;/h3&gt;

&lt;p&gt;As already mentioned above, the commit object contains a pointer to the snapshot. In this case, our tree checksum for &lt;code&gt;dir-1&lt;/code&gt; would be the snapshot and its pointer is saved in the commit object.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VEj7cYrL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/283179thmp8zq9d9ln7n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VEj7cYrL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/283179thmp8zq9d9ln7n.png" alt="" width="700" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If it is the first commit of the repository, the pointer to the previous commit is &lt;code&gt;null&lt;/code&gt;. The next commit will point to the first commit, the third commit will point to the second commit and so on. In Git language, the previous commit is called a commit's parent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bYrRtt2G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2vbtylmau4j6nvcilin.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bYrRtt2G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t2vbtylmau4j6nvcilin.png" alt="" width="700" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;In this post, you got a glimpse of how Git commits work internally and probably have an inkling of the reason behind Git's lightweightness and speed.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell"&gt;https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Git Tags Continued - Share, Delete and Checkout</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Wed, 16 Aug 2023 08:22:00 +0000</pubDate>
      <link>https://dev.to/ello/git-tags-continued-share-delete-and-checkout-4p0n</link>
      <guid>https://dev.to/ello/git-tags-continued-share-delete-and-checkout-4p0n</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/ello/introduce-checkpoints-in-your-code-learn-how-to-use-tagging-in-git-811"&gt;previous post introducing Git tags&lt;/a&gt;, we learnt what Git tags are, how they are created and how we can view the existing tags. By default, when we run &lt;code&gt;git push&lt;/code&gt;, Git does not push the tags you have created to the remote server (eg: &lt;a href="https://github.com"&gt;Github&lt;/a&gt;). We need to be explicit in our intention when we want to push the tags to the remote server.&lt;/p&gt;

&lt;p&gt;This post will be a continuation of the &lt;a href="https://dev.to/ello/introduce-checkpoints-in-your-code-learn-how-to-use-tagging-in-git-811"&gt;previous post&lt;/a&gt;, discussing on the following points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to push tags to a remote server&lt;/li&gt;
&lt;li&gt;How to delete tags (locally and in the remote server)&lt;/li&gt;
&lt;li&gt;Create branches based off a tag&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to push tags to a remote server
&lt;/h2&gt;

&lt;p&gt;As already mentioned, merely running &lt;code&gt;git push&lt;/code&gt; won't push the tags. In order to push tags to the remote server, we need to use the &lt;code&gt;--tags&lt;/code&gt; flag. Hence the command would be:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="c"&gt;# In case you want to push to a different origin&lt;/span&gt;
git push &amp;lt;remote&amp;gt; &lt;span class="nt"&gt;--tags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Using the &lt;code&gt;--tags&lt;/code&gt; flag will push both &lt;a href="https://dev.to/ello/introduce-checkpoints-in-your-code-learn-how-to-use-tagging-in-git-811"&gt;annotated and lightweight tags&lt;/a&gt;. If you want to push the &lt;a href="https://dev.to/ello/introduce-checkpoints-in-your-code-learn-how-to-use-tagging-in-git-811"&gt;annotated tags only&lt;/a&gt;, then you can use the &lt;code&gt;--follow-tags&lt;/code&gt; flag instead.&lt;/p&gt;

&lt;p&gt;There is no way to push just the &lt;a href="https://dev.to/ello/introduce-checkpoints-in-your-code-learn-how-to-use-tagging-in-git-811"&gt;lightweight tags&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to delete a tag
&lt;/h2&gt;

&lt;p&gt;The command to delete a tag in your local Git repository is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git tag &lt;span class="nt"&gt;-d&lt;/span&gt; &amp;lt;tagname&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deleting the tag in the remote server
&lt;/h3&gt;

&lt;p&gt;If the tag has been pushed to the remote server before deleting it in the local Git repository, you need to run another explicit command to delete the tag from the remote server too. The command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &amp;lt;remote&amp;gt; &lt;span class="nt"&gt;--delete&lt;/span&gt; &amp;lt;tagname&amp;gt;

&lt;span class="c"&gt;# Example&lt;/span&gt;
git push origin &lt;span class="nt"&gt;--delete&lt;/span&gt; v1.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;There is another way to delete a tag in the remote server. The command is:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &amp;lt;remote&amp;gt; :refs/tags/&amp;lt;tagname&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The explanation of this command is: Push the part before the colon (&lt;code&gt;:&lt;/code&gt;) to the remote tag named &lt;code&gt;&amp;lt;tagname&amp;gt;&lt;/code&gt;. In this case, the part before the colon (&lt;code&gt;:&lt;/code&gt;) is &lt;strong&gt;null&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to create a branch based off a tag
&lt;/h2&gt;

&lt;p&gt;The general command to create a branch is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &amp;lt;newBranch&amp;gt; &amp;lt;reference&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;reference&lt;/code&gt; can be any valid Git object. Using this command, a new branch based off a tag can be created using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &amp;lt;newBranch&amp;gt; &amp;lt;tagname&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are looking to just explore the code that is versioned by the tag, you can also directly checkout the tag using: &lt;code&gt;git checkout &amp;lt;tagname&amp;gt;&lt;/code&gt;. Using this command puts your repository in &lt;a href="https://circleci.com/blog/git-detached-head-state/#what-does-detached-head-mean"&gt;detached HEAD&lt;/a&gt; state. You can use the link provided to learn more about it. I will also be exploring it in a future post of mine.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR of detached HEAD&lt;/strong&gt;: In "detached HEAD", if you make some changes and commit them, the changes will not belong to any branch and will be lost. The only way to reach the commit would be by using its commit hash.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;My hope is that by now, you are well equipped with dealing with the basics of Git tags, and are ready to tackle any new concepts that are thrown your way. Again, I also recommend reading my &lt;a href="https://dev.to/ello/introduce-checkpoints-in-your-code-learn-how-to-use-tagging-in-git-811"&gt;first post on Git tags&lt;/a&gt;.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Tagging"&gt;https://git-scm.com/book/en/v2/Git-Basics-Tagging&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Introduce checkpoints in your code - Learn how to use tagging in Git</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Tue, 15 Aug 2023 08:49:00 +0000</pubDate>
      <link>https://dev.to/ello/introduce-checkpoints-in-your-code-learn-how-to-use-tagging-in-git-811</link>
      <guid>https://dev.to/ello/introduce-checkpoints-in-your-code-learn-how-to-use-tagging-in-git-811</guid>
      <description>&lt;p&gt;Tags in Git can be likened to checkpoints of a game. You can tag points in a repository's history that are important to you. Typically, tags are used to mark release versions like &lt;code&gt;v1.0.0&lt;/code&gt;, &lt;code&gt;v2.0.0&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;Tags are associated with a specific commit in your repository. In other words, after you create a commit, you can tag that commit with any name of you liking - e.g., &lt;code&gt;v1.0.0&lt;/code&gt;, &lt;code&gt;v2.0.0&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;In this post, I am going to tell you about the two types of tags in Git and how to create them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of tags
&lt;/h2&gt;

&lt;p&gt;There are two types of tags in Git:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lightweight&lt;/li&gt;
&lt;li&gt;Annotated&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Lightweight tags
&lt;/h3&gt;

&lt;p&gt;These tags are simply pointers to a commit. You can think of them as "bookmarks" to a commit. They cannot store any metadata apart from the name of the tag itself. As a best practice, these tags are generally used for temporary bookmarking and private use.&lt;/p&gt;

&lt;p&gt;The command to create a lightweight tag is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git tag &amp;lt;tagname&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;tagname&lt;/code&gt; can be anything that you want.&lt;/p&gt;

&lt;h3&gt;
  
  
  Annotated tags
&lt;/h3&gt;

&lt;p&gt;Annotated tags are stored as independent objects in the Git database, with its own SHA1 hash, and metadata. They are capable of storing metadata such as author of the tag, email of the tagger, date of tagging and a message describing the tag. The command to create an annotated tag is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git tag &lt;span class="nt"&gt;-a&lt;/span&gt; &amp;lt;tagname&amp;gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &amp;lt;message&amp;gt;

&lt;span class="c"&gt;# Example&lt;/span&gt;
git tag &lt;span class="nt"&gt;-a&lt;/span&gt; v1.0.0 &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"App is open to the public now"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you provide a message using the &lt;code&gt;-m&lt;/code&gt; flag, then you don't even need to provide the &lt;code&gt;-a&lt;/code&gt; flag. You can just do: &lt;code&gt;git tag &amp;lt;tagname&amp;gt; -m &amp;lt;message&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Annotated tags are useful when you want to push the tag to the public domain. They are useful because they can hold metadata like tagger's name and date of tagging. This information can help, for example, when trying to track the root cause of a bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can a tag only point to the latest commit?
&lt;/h2&gt;

&lt;p&gt;No. You can also create a tag that points to a previous commit. Consider the following git log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;305e248 - Ayush Poddar, 10 weeks ago : refactor: split into two methods
6f7f4ab - Ayush Poddar, 10 weeks ago : modify the instance doubles ensuring green specs
fe59bb7 - Ayush Poddar, 10 weeks ago : add logic to show different color for hidden files/directories
4f1333f - Ayush Poddar, 10 weeks ago : add colors for hidden files/directories
1e1f10c - Ayush Poddar, 10 weeks ago : modify indentations
28c188b - Claudio Bley, 3 months ago : Merge pull request #594 from ayushpoddar/show-abs-path-xargs
44c370b - Ayush Poddar, 3 months ago : Revert "version bump"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What if we want to create a tag that points to commit &lt;code&gt;1e1f10c&lt;/code&gt; (modify indentations)? You can simply add the commit hash (&lt;code&gt;1e1f10c&lt;/code&gt;) at the end of the &lt;code&gt;git tag&lt;/code&gt; command. So the command would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Lightweight tag&lt;/span&gt;
git tag &amp;lt;tagname&amp;gt; 1e1f10c

&lt;span class="c"&gt;# Annotated tag&lt;/span&gt;
git tag &lt;span class="nt"&gt;-a&lt;/span&gt; &amp;lt;tagname&amp;gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &amp;lt;tag message&amp;gt; 1e1f10c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Viewing details of a tag
&lt;/h2&gt;

&lt;p&gt;To view details of a tag, you can use the &lt;code&gt;git show&lt;/code&gt; command. The command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git show &amp;lt;tagname&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output differs slightly for lightweight and annotated tags. In case of lightweight tags, only the associated commit's information is displayed. The sample output is shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;commit 305e2486f4431fc7e0487423f90ed380852194b2
Author: Ayush Poddar &amp;lt;ayush.mail.id@gmail.com&amp;gt;
Date:   Wed Jun 7 18:00:34 2023 +0530
&lt;/span&gt;
    refactor: split into two methods

diff --git a/lib/colorls/core.rb b/lib/colorls/core.rb
&lt;span class="gh"&gt;index b558968..f5f7707 100644
&lt;/span&gt;&lt;span class="gd"&gt;--- a/lib/colorls/core.rb
&lt;/span&gt;&lt;span class="gi"&gt;+++ b/lib/colorls/core.rb
&lt;/span&gt;&lt;span class="p"&gt;@@ -416,20 +416,32 @@&lt;/span&gt; module ColorLS

     def options(content)
       if content.directory?
&lt;span class="gd"&gt;-        key = content.name.downcase.to_sym
-        key = @folder_aliases[key] unless @folders.key? key
-        key = :folder if key.nil?
-        color = content.hidden? ? @colors[:hidden_dir] : @colors[:dir]
-        group = :folders
&lt;/span&gt;&lt;span class="gi"&gt;+        options_directory(content).values_at(:key, :color, :group)
&lt;/span&gt;       else
&lt;span class="gd"&gt;-        key = File.extname(content.name).delete_prefix('.').downcase.to_sym
-        key = @file_aliases[key] unless @files.key? key
-        color = file_color(content, key)
-        group = @files.key?(key) ? :recognized_files : :unrecognized_files
-        key = :file if key.nil?
&lt;/span&gt;&lt;span class="gi"&gt;+        options_file(content).values_at(:key, :color, :group)
&lt;/span&gt;       end
&lt;span class="gi"&gt;+    end
+
+    def options_directory(content)
+      key = content.name.downcase.to_sym
+      key = @folder_aliases[key] unless @folders.key?(key)
+      key = :folder if key.nil?
+
+      color = content.hidden? ? @colors[:hidden_dir] : @colors[:dir]
+
+      {key: key, color: color, group: :folders}
+    end
+
+    def options_file(content)
+      key = File.extname(content.name).delete_prefix('.').downcase.to_sym
+      key = @file_aliases[key] unless @files.key?(key)
+
+      color = file_color(content, key)
+      group = @files.key?(key) ? :recognized_files : :unrecognized_files
+
+      key = :file if key.nil?
&lt;/span&gt;
-      [key, color, group]
&lt;span class="gi"&gt;+      {key: key, color: color, group: group}
&lt;/span&gt;     end

     def tree_contents(path)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In case of annotated tags, additional metadata such as tagger name, tagging date, etc. are also displayed. A sample output is given below. Notice the metadata displayed above the commit information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;tag annotated-tag
Tagger: Ayush Poddar &amp;lt;ayush.mail.id@gmail.com&amp;gt;
Date:   Tue Aug 15 13:38:36 2023 +0530
&lt;/span&gt;
This is the sample tag

commit 305e2486f4431fc7e0487423f90ed380852194b2
&lt;span class="p"&gt;Author: Ayush Poddar &amp;lt;ayush.mail.id@gmail.com&amp;gt;
Date:   Wed Jun 7 18:00:34 2023 +0530
&lt;/span&gt;
    refactor: split into two methods

diff --git a/lib/colorls/core.rb b/lib/colorls/core.rb
&lt;span class="gh"&gt;index b558968..f5f7707 100644
&lt;/span&gt;&lt;span class="gd"&gt;--- a/lib/colorls/core.rb
&lt;/span&gt;&lt;span class="gi"&gt;+++ b/lib/colorls/core.rb
&lt;/span&gt;&lt;span class="p"&gt;@@ -416,20 +416,32 @@&lt;/span&gt; module ColorLS

     def options(content)
       if content.directory?
&lt;span class="gd"&gt;-        key = content.name.downcase.to_sym
-        key = @folder_aliases[key] unless @folders.key? key
-        key = :folder if key.nil?
-        color = content.hidden? ? @colors[:hidden_dir] : @colors[:dir]
-        group = :folders
&lt;/span&gt;&lt;span class="gi"&gt;+        options_directory(content).values_at(:key, :color, :group)
&lt;/span&gt;       else
&lt;span class="gd"&gt;-        key = File.extname(content.name).delete_prefix('.').downcase.to_sym
-        key = @file_aliases[key] unless @files.key? key
-        color = file_color(content, key)
-        group = @files.key?(key) ? :recognized_files : :unrecognized_files
-        key = :file if key.nil?
&lt;/span&gt;&lt;span class="gi"&gt;+        options_file(content).values_at(:key, :color, :group)
&lt;/span&gt;       end
&lt;span class="gi"&gt;+    end
+
+    def options_directory(content)
+      key = content.name.downcase.to_sym
+      key = @folder_aliases[key] unless @folders.key?(key)
+      key = :folder if key.nil?
+
+      color = content.hidden? ? @colors[:hidden_dir] : @colors[:dir]
+
+      {key: key, color: color, group: :folders}
+    end
+
+    def options_file(content)
+      key = File.extname(content.name).delete_prefix('.').downcase.to_sym
+      key = @file_aliases[key] unless @files.key?(key)
+
+      color = file_color(content, key)
+      group = @files.key?(key) ? :recognized_files : :unrecognized_files
+
+      key = :file if key.nil?
&lt;/span&gt;
-      [key, color, group]
&lt;span class="gi"&gt;+      {key: key, color: color, group: group}
&lt;/span&gt;     end

     def tree_contents(path)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Listing tags
&lt;/h2&gt;

&lt;p&gt;To list all tags in a repository, you can use the &lt;code&gt;git tag&lt;/code&gt; command &lt;em&gt;(without any arguments)&lt;/em&gt;. You can also supply the &lt;code&gt;--list&lt;/code&gt; (&lt;code&gt;-l&lt;/code&gt;) flag which takes an optional argument.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;git tag --list&lt;/code&gt;, as it is, will also list all the tags just like &lt;code&gt;git tag&lt;/code&gt; would. The sample output of running &lt;code&gt;git tag --list&lt;/code&gt; or &lt;code&gt;git tag&lt;/code&gt; is shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v1.0.0
v1.0.1
v1.0.2
v1.0.3
v1.0.4
v1.0.5
v1.0.7
v1.0.8
v1.0.9
v1.1.0
v1.1.1
v1.2.0
v1.3.0
v1.3.1
v1.3.2
v1.3.3
v1.4.0
v1.4.1
v1.4.2
v1.4.3
v1.4.4
v1.4.5
v1.4.6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to filter the tags by their name?
&lt;/h3&gt;

&lt;p&gt;You can provide an argument to the &lt;code&gt;--list&lt;/code&gt; flag to filter the tags. The argument needs to be the pattern that you want to filter by. The pattern can be the exact string to match or a &lt;a href="https://linuxhint.com/bash_wildcard_tutorial/"&gt;shell wildcard&lt;/a&gt;. For example, if we want to view only those tags which start with "v1.0", we can do:&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 tag &lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="s1"&gt;'v1.0.*'&lt;/span&gt;

&lt;span class="c"&gt;# Output&lt;/span&gt;
v1.0.0
v1.0.1
v1.0.2
v1.0.3
v1.0.4
v1.0.5
v1.0.7
v1.0.8
v1.0.9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to filter for multiple patterns?
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;--list&lt;/code&gt; flag can also take multiple arguments. In such a case, all tags which match &lt;strong&gt;any&lt;/strong&gt; of the provided patterns will be listed. For example, if we want to list all tags which start with "v1.0", along with the tags which start with "v1.4" we can do:&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 tag &lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="s1"&gt;'v1.0.*'&lt;/span&gt; &lt;span class="s1"&gt;'v1.4.*'&lt;/span&gt;

&lt;span class="c"&gt;# Output&lt;/span&gt;
v1.0.0
v1.0.1
v1.0.2
v1.0.3
v1.0.4
v1.0.5
v1.0.7
v1.0.8
v1.0.9
v1.4.0
v1.4.1
v1.4.2
v1.4.3
v1.4.4
v1.4.5
v1.4.6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In this post, you learned about Git tags and the different types of tags supported by it. You also learned:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to create tags&lt;/li&gt;
&lt;li&gt;view details of a specific tag&lt;/li&gt;
&lt;li&gt;List all the tags and filter them by their name&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/a/4971817/6212985"&gt;This stackoverflow answer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.atlassian.com/git/tutorials/inspecting-a-repository/git-tag#:~:text=Annotated%20tags%20store%20extra%20meta,quick%20links%20to%20relevant%20commits."&gt;https://www.atlassian.com/git/tutorials/inspecting-a-repository/git-tag&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Tagging"&gt;https://git-scm.com/book/en/v2/Git-Basics-Tagging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/docs/git-tag"&gt;https://git-scm.com/docs/git-tag&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Git Remotes for Beginners: Inspect, Rename and Remove</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Mon, 14 Aug 2023 07:17:40 +0000</pubDate>
      <link>https://dev.to/ello/git-remotes-for-beginners-inspect-rename-and-remove-48f</link>
      <guid>https://dev.to/ello/git-remotes-for-beginners-inspect-rename-and-remove-48f</guid>
      <description>&lt;p&gt;In the &lt;a href="https://poddarayush.com/posts/git-remote-commands"&gt;previous post, I introduced you to the concept of Git remotes&lt;/a&gt;. I showed you that a Git repository can have more than one remote and how you can fetch data from a particular remote.&lt;/p&gt;

&lt;p&gt;In this post, I am about to answer the following questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How do you view more details about a particular remote? The branches present in the remote, and how those branches map to your local branches.&lt;/li&gt;
&lt;li&gt;How do you rename a remote?&lt;/li&gt;
&lt;li&gt;How do you stop tracking (remove) a remote from your Git repository?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  View (Inspect) a Git remote
&lt;/h2&gt;

&lt;p&gt;The command to achieve this is: &lt;code&gt;git remote show &amp;lt;shortname&amp;gt;&lt;/code&gt;. For example, the sample output of running &lt;code&gt;git remote show origin&lt;/code&gt; is shown below.&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="k"&gt;*&lt;/span&gt; remote origin
  Fetch URL: git@github.com:ayushpoddar/colorls.git
  Push  URL: git@github.com:ayushpoddar/colorls.git
  HEAD branch: main
  Remote branches:
    color-hidden-files  tracked
    main                tracked
    show-abs-path-xargs tracked
    size-in-bytes       tracked
  Local branches configured &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s1"&gt;'git pull'&lt;/span&gt;:
    color-hidden-files  merges with remote color-hidden-files
    main                merges with remote main
    show-abs-path-xargs merges with remote show-abs-path-xargs
    size-in-bytes       merges with remote size-in-bytes
  Local refs configured &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s1"&gt;'git push'&lt;/span&gt;:
    color-hidden-files  pushes to color-hidden-files  &lt;span class="o"&gt;(&lt;/span&gt;up to &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    main                pushes to main                &lt;span class="o"&gt;(&lt;/span&gt;up to &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    show-abs-path-xargs pushes to show-abs-path-xargs &lt;span class="o"&gt;(&lt;/span&gt;up to &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    size-in-bytes       pushes to size-in-bytes       &lt;span class="o"&gt;(&lt;/span&gt;up to &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I want you make the following observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This command outputs the full URL of the remote that the shortname is mapped to.&lt;/li&gt;
&lt;li&gt;The list of branches in remote have been "fetched" to your local repository.&lt;/li&gt;
&lt;li&gt;It lists the mapping between your local branches and remote branches. This helps you with knowing the remote branch that will be used when running &lt;code&gt;git pull&lt;/code&gt; or &lt;code&gt;git push&lt;/code&gt; on a local branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are wondering if the branch names in remote and the corresponding branch names in local can be different, I would encourage you to read &lt;a href="https://docs.github.com/en/get-started/using-git/pushing-commits-to-a-remote-repository#renaming-branches"&gt;this Github article&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to rename a remote shortname?
&lt;/h2&gt;

&lt;p&gt;Simple command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote rename &amp;lt;old-shortname&amp;gt; &amp;lt;new-shortname&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to remove a remote?
&lt;/h2&gt;

&lt;p&gt;If you want to stop tracking a remote, you need to remove all references to the remote from your local repository. The command to do so is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote remove &amp;lt;shortname&amp;gt;

&lt;span class="c"&gt;# rm is an alias for remove&lt;/span&gt;
git remote &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;shortname&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;After reading the &lt;a href="https://poddarayush.com/posts/git-remote-commands"&gt;first post&lt;/a&gt; and this post, you are equipped enough to understand any advanced ideas or commands that you may encounter. You can explore more on your own using &lt;code&gt;man git-remote&lt;/code&gt; or &lt;code&gt;git help remote&lt;/code&gt;.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes"&gt;https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Git Remotes for Beginners: An Introductory Guide</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Sun, 13 Aug 2023 12:37:07 +0000</pubDate>
      <link>https://dev.to/ello/git-remotes-for-beginners-an-introductory-guide-53i2</link>
      <guid>https://dev.to/ello/git-remotes-for-beginners-an-introductory-guide-53i2</guid>
      <description>&lt;p&gt;If you have read my post on &lt;a href="https://poddarayush.com/posts/history-of-git"&gt;the history of Git&lt;/a&gt;, you would know that in order to have effective collaboration, we need to have a &lt;a href="https://poddarayush.com/shorts/git-storage-of-versions"&gt;version database&lt;/a&gt; that is accessible to everyone on the team.&lt;/p&gt;

&lt;p&gt;You must also be aware of &lt;a href="https://github.com/"&gt;Github&lt;/a&gt; which is a very popular service that helps developers maintain their Git repositories online and enable easy collaboration by acting as the central &lt;a href="https://poddarayush.com/shorts/git-storage-of-versions"&gt;version database&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this post, I am interested in introducing you to the concept of &lt;strong&gt;Git remotes&lt;/strong&gt;. The repository that you have uploaded to Github is an example of a &lt;strong&gt;Git remote&lt;/strong&gt;. It is basically a copy of your local Git repository that is accessible to anyone you choose to share your repository with.&lt;/p&gt;

&lt;h2&gt;
  
  
  There can be more than one remote
&lt;/h2&gt;

&lt;p&gt;Your repository can have multiple remotes, i.e., multiple remote copies of the repository with different read/write permissions for different users. A common case for multiple remotes is in the world of open source projects.&lt;/p&gt;

&lt;p&gt;Generally, contributors clone the primary project repository and maintain their own remote copy of the repository &lt;em&gt;(ever heard of forking?)&lt;/em&gt;, where they push any changes they make. After they are sure of the changes they have made, they request the project maintainers to pull those changes into the primary repository.&lt;/p&gt;

&lt;p&gt;A Git remote is represented by the URL of the repository. You must have seen URLs which are of the form &lt;code&gt;git://github.com/&amp;lt;username&amp;gt;/&amp;lt;repo-name&amp;gt;&lt;/code&gt;. Since remembering URLs is difficult, Git also allows you to assign &lt;strong&gt;shortnames&lt;/strong&gt; that map to these URLs. By default, when you clone a Git repository, Git assigns the shortname &lt;code&gt;origin&lt;/code&gt; to the URL from where you have cloned.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to list all remotes?
&lt;/h2&gt;

&lt;p&gt;The command &lt;code&gt;git remote&lt;/code&gt; lists all the remotes associated with your repository. Without any options, it just lists the shortnames. If you want to view the associated URLs too, then you need to use the &lt;code&gt;--verbose&lt;/code&gt; (&lt;code&gt;-v&lt;/code&gt;) option. Below is the sample output of the &lt;code&gt;git remote -v&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;origin  git@github.com:ayushpoddar/colorls.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
origin  git@github.com:ayushpoddar/colorls.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
upstream    https://github.com/athityakumar/colorls.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
upstream    https://github.com/athityakumar/colorls.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to add a remote repository?
&lt;/h2&gt;

&lt;p&gt;Apart from the default &lt;code&gt;origin&lt;/code&gt; remote, you can add a remote to your repository explicitly. The command for doing so is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote add &amp;lt;shortname&amp;gt; &amp;lt;url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;shortname&lt;/code&gt; can be anything that you choose. As an example, you can add a remote named &lt;code&gt;upstream&lt;/code&gt; with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote add upstream https://github.com/athityakumar/colorls.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to fetch all the information from this new remote, you could run &lt;code&gt;git fetch &amp;lt;shortname&amp;gt;&lt;/code&gt;. For example, running &lt;code&gt;git fetch upstream&lt;/code&gt; in context of the above examples will output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;remote: Enumerating objects: 4, &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;4/4&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 4 &lt;span class="o"&gt;(&lt;/span&gt;delta 3&lt;span class="o"&gt;)&lt;/span&gt;, reused 4 &lt;span class="o"&gt;(&lt;/span&gt;delta 3&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused 0
Unpacking objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;4/4&lt;span class="o"&gt;)&lt;/span&gt;, 555 bytes | 61.00 KiB/s, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
From https://github.com/athityakumar/colorls
 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;new branch]      disable-mfa -&amp;gt; upstream/disable-mfa
   d1e28ed..28c188b  main        -&amp;gt; upstream/main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now access upstream's main branch at &lt;code&gt;upstream/main&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you try to run &lt;code&gt;git checkout upstream/main&lt;/code&gt;, Git will display an elaborate warning. I will get into the details of this warning in a later post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Does "git fetch" make any modifications?
&lt;/h3&gt;

&lt;p&gt;No, it just downloads the repository data to your local repository. It does not merge any changes or modify any of your files.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes"&gt;https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>Un-stage and un-modify a file in Git - Part 2</title>
      <dc:creator>Ayush Poddar</dc:creator>
      <pubDate>Sat, 12 Aug 2023 03:37:09 +0000</pubDate>
      <link>https://dev.to/ello/un-stage-and-un-modify-a-file-in-git-part-2-4enf</link>
      <guid>https://dev.to/ello/un-stage-and-un-modify-a-file-in-git-part-2-4enf</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is part of my &lt;a href="https://poddarayush.com/shorts"&gt;“Shorts”&lt;/a&gt; series, where each post is concise and hyper-focused on a single concept.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In a &lt;a href="https://poddarayush.com/shorts/unstage-a-file/"&gt;previous post&lt;/a&gt;, we learned about the &lt;code&gt;git rm&lt;/code&gt; command which helps you un-stage a file, and delete any modifications made. However, the &lt;code&gt;git rm&lt;/code&gt; command is essentially meant to “delete” files, not undo them.&lt;/p&gt;

&lt;p&gt;Git offers a dedicated command to undo modifications, or undo staging of a file. In this post, I will introduce you to &lt;code&gt;git restore&lt;/code&gt; which can be used to perform both these tasks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Git introduced &lt;code&gt;git restore&lt;/code&gt; in version 2.23.0. Earlier, the commands &lt;code&gt;git reset&lt;/code&gt; and &lt;code&gt;git checkout&lt;/code&gt; were used for the same purposes. But, &lt;code&gt;git restore&lt;/code&gt; was introduced as a more dedicated tool for these specific purposes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I will not cover the details of the &lt;code&gt;git restore&lt;/code&gt; command since Git is very helpful with these commands, and I think it is best for you to explore them yourself. When you run &lt;code&gt;git status&lt;/code&gt;, Git exactly tells you the commands to un-stage or undo any unstaged modifications. This is how the output of &lt;code&gt;git status&lt;/code&gt; looks like. Notice the commands mentioned for undo-ing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;On branch main
Your branch is ahead of 'origin/main' by 1 commit.
&lt;/span&gt;  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git restore --staged &amp;lt;file&amp;gt;..." to unstage)
    renamed:    README.md -&amp;gt; README

Changes not staged for commit:
  (use "git add &amp;lt;file&amp;gt;..." to update what will be committed)
  (use "git restore &amp;lt;file&amp;gt;..." to discard changes in working directory)
    modified:   ammend.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fair warning
&lt;/h2&gt;

&lt;p&gt;If you use &lt;code&gt;git restore &amp;lt;file&amp;gt;&lt;/code&gt; to undo any unstaged modifications to a file, then you will lose all those changes forever. Git only helps you recover changes that have ever been committed.&lt;/p&gt;

&lt;p&gt;If you are feeling uneasy about losing those modifications forever, but still want to undo the modifications, a better way is to use &lt;code&gt;git stash&lt;/code&gt;. I will explore this command in a later post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further exploration
&lt;/h2&gt;

&lt;p&gt;As always, I encourage you to explore the command further using &lt;code&gt;man git-restore&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>git</category>
    </item>
  </channel>
</rss>
