<?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: Goran Vasic</title>
    <description>The latest articles on DEV Community by Goran Vasic (@goranvasic).</description>
    <link>https://dev.to/goranvasic</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%2F475540%2Fdab06535-11b7-453a-99a1-6df31ff6f9f3.jpeg</url>
      <title>DEV Community: Goran Vasic</title>
      <link>https://dev.to/goranvasic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/goranvasic"/>
    <language>en</language>
    <item>
      <title>Using Zsh and zsh-autosuggestions on Windows Terminal with Oh My Posh theme</title>
      <dc:creator>Goran Vasic</dc:creator>
      <pubDate>Sat, 08 Jun 2024 18:05:05 +0000</pubDate>
      <link>https://dev.to/goranvasic/using-zsh-and-zsh-autosuggestions-on-windows-terminal-with-oh-my-posh-theme-do6</link>
      <guid>https://dev.to/goranvasic/using-zsh-and-zsh-autosuggestions-on-windows-terminal-with-oh-my-posh-theme-do6</guid>
      <description>&lt;p&gt;This article contains unstructions on how to configure Windows Terminal to use Oh My Posh with Zsh and zsh-autosuggestions.&lt;/p&gt;

&lt;p&gt;This approach is not relying on &lt;a href="https://learn.microsoft.com/en-us/windows/wsl/"&gt;WSL&lt;/a&gt;, it is utilizing existing Git installation on Windows. This way, you can have fully functional Zsh shell with autocomplete natively on Windows, just like you would on Mac.&lt;/p&gt;




&lt;p&gt;Some people recommend using &lt;a href="https://github.com/akinomyoga/ble.sh"&gt;ble.sh – Bash Line Editor&lt;/a&gt;, a command line editor written in pure Bash which replaces the default GNU Readline (mentioned in &lt;a href="https://www.youtube.com/watch?v=dRdGq8khTJc"&gt;Bash vs ZSH vs Fish: What's the Difference?&lt;/a&gt;). However, on Windows I still prefer using Zsh with &lt;code&gt;zsh-autosuggestions&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Instructions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Download and install Git from &lt;a href="https://git-scm.com/"&gt;git-scm&lt;/a&gt;. Make sure to uncheck suggested options for Git Bash (e.g. the 2 options under "Windows Explorer integration"). You can select the option to add a Git Bash Profile to Windows Terminal, we will modify it manually later. When asked about adjusting your PATH environment, I like to use the Recommended setting, and I also like to enable symbolic links. I usually keep everything else on default.&lt;/li&gt;
&lt;li&gt;From Microsoft Store, install &lt;a href="https://www.microsoft.com/store/productId/9N0DX20HK701"&gt;Windows Terminal&lt;/a&gt; and &lt;code&gt;winget&lt;/code&gt; &lt;a href="https://www.microsoft.com/store/productId/9NBLGGH4NNS1"&gt;App Installer&lt;/a&gt;. Check if everything has been installed properly by opening a new Windows Terminal session and typing &lt;code&gt;winget --version&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open your Windows Start menu, and search for "PowerShell".&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run Windows PowerShell as Administrator, then install &lt;a href="https://ohmyposh.dev/docs/installation/windows"&gt;Oh My Posh&lt;/a&gt; using &lt;code&gt;winget&lt;/code&gt;, for example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;winget &lt;span class="nb"&gt;install &lt;/span&gt;JanDeDobbeleer.OhMyPosh &lt;span class="nt"&gt;-s&lt;/span&gt; winget
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Close PowerShell, then add &lt;code&gt;oh-my-posh&lt;/code&gt; path to your Windows environment variables (User):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Press &lt;code&gt;Win + r&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Type in &lt;code&gt;control&lt;/code&gt; and hit &lt;code&gt;ENTER&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to "User Accounts".&lt;/li&gt;
&lt;li&gt;Click on "User Accounts" one more time, then click the "Change my environment variables" link on the left side to open the "Environment Variables" window.&lt;/li&gt;
&lt;li&gt;In the upper (User) part of the window, scroll down and select &lt;code&gt;Path&lt;/code&gt;, then click the &lt;code&gt;Edit...&lt;/code&gt; button.&lt;/li&gt;
&lt;li&gt;Depending on the way your variables are displayed, either click &lt;code&gt;New&lt;/code&gt; to add a new variable, or add a &lt;code&gt;;&lt;/code&gt; at the end of the line, then type in &lt;code&gt;%LOCALAPPDATA%\Programs\oh-my-posh\bin&lt;/code&gt; for the value. It might be that this value already exists, in which case you don't need to edit anything.&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;OK&lt;/code&gt;, then confirm every previously opened window by clicking &lt;code&gt;OK&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run PowerShell one more time with Administrator privileges, then install either the &lt;code&gt;FiraCode Nerd Font&lt;/code&gt; or &lt;code&gt;SauceCodePro Nerd Font&lt;/code&gt; (I prefer &lt;code&gt;SourceCodePro&lt;/code&gt;) from &lt;a href="https://www.nerdfonts.com/font-downloads"&gt;Nerd Fonts&lt;/a&gt; using the following command (follow their instructions in order to select the desired font):&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;oh-my-posh font &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start a new Git Bash terminal by double-clicking on &lt;code&gt;git-bash.exe&lt;/code&gt; located under &lt;code&gt;C:\Program Files\Git\&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Download the &lt;a href="https://packages.msys2.org/package/zsh?repo=msys&amp;amp;variant=x86_64"&gt;Zsh for Windows package&lt;/a&gt; &lt;code&gt;zsh~x86_64.pkg.tar.zst&lt;/code&gt; by executing the following command:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsLo&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/zsh-5.9-2-x86_64.pkg.tar.zst https://mirror.msys2.org/msys/x86_64/zsh-5.9-2-x86_64.pkg.tar.zst
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In Windows Explorer, locate the downloaded &lt;code&gt;.zst&lt;/code&gt; file in your home directory and extract it either using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://peazip.github.io/"&gt;PeaZip&lt;/a&gt;, which can be installed using the &lt;code&gt;winget install -e peazip&lt;/code&gt; command, or&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.7-zip.org/download.html"&gt;7-Zip&lt;/a&gt; (I prefer this option, since I already have it installed).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You only need the &lt;code&gt;etc&lt;/code&gt; and &lt;code&gt;usr&lt;/code&gt; directories, so copy these two directories from the extracted folder into &lt;code&gt;C:\Program Files\Git&lt;/code&gt; and when prompted, select the option to overwrite all existing files – don't worry, these two directories (&lt;code&gt;etc&lt;/code&gt; and &lt;code&gt;usr&lt;/code&gt;) contain completely new files, no existing files will be overwritten.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Open &lt;code&gt;%PROGRAMFILES%/Git/etc/profile&lt;/code&gt; in your text editor as Administrator (because you might need elevated privileges in order to save the changes) and:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comment out the entire block near the bottom of the file that starts with line &lt;code&gt;if [ ! "x${BASH_VERSION}" = "x" ]; then&lt;/code&gt; and ends with line &lt;code&gt;fi&lt;/code&gt;. At the moment of writing the article, I commented out lines &lt;code&gt;111-133&lt;/code&gt;. We don't need all of this code since we know we will be using Zsh.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Below the commented out block, add the following 3 lines:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;HOSTNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt; /usr/bin/hostname&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
profile_d zsh
&lt;span class="nv"&gt;SHELL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/usr/bin/zsh'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the changes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the Windows Start menu, search for "Terminal" and start it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Open Windows Terminal's settings using the &lt;code&gt;Ctrl + Shift + ,&lt;/code&gt; keyboard shortcut, then under the &lt;code&gt;profiles &amp;gt; list&lt;/code&gt; array modify the existing Bash profile, or add a new profile:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Git Bash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"guid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{12398ec4-4e3d-5e58-b989-0a998ec441b1}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"commandline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"%PROGRAMFILES%/git/usr/bin/zsh.exe -il"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"%USERPROFILE%/git.ico"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"startingDirectory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"%USERPROFILE%"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"colorScheme"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VibrantInk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"font"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"face"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SauceCodePro NFM"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"useAcrylic"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"opacity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"adjustIndistinguishableColors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bellStyle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hidden"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HINT: For the code mentioned above, make sure to add the &lt;code&gt;,&lt;/code&gt; character after the closing curly brace, if needed, so that the settings file syntax is valid. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The profile above uses a custom &lt;code&gt;~/git.ico&lt;/code&gt; icon, so you can either reference the default &lt;code&gt;git-for-windows.ico&lt;/code&gt; icon file under &lt;code&gt;C:\Program Files\Git\mingw64\share\git&lt;/code&gt; or find another one you like.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you wish, you can also set the above profile to be your default Windows Terminal profile by setting the same &lt;code&gt;guid&lt;/code&gt; as the &lt;code&gt;defaultProfile&lt;/code&gt; value in the settings JSON.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Restart Windows Terminal and verify that everything is working (configure &lt;code&gt;zsh&lt;/code&gt; using the interactive menu).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Execute the following command from any location to install &lt;a href="https://ohmyz.sh/"&gt;Oh My Zsh&lt;/a&gt; under your &lt;code&gt;$HOME/.oh-my-zsh&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Clone &lt;code&gt;zsh-autosuggestions&lt;/code&gt; using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/zsh-users/zsh-autosuggestions.git &lt;span class="nv"&gt;$ZSH_CUSTOM&lt;/span&gt;/plugins/zsh-autosuggestions
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Open &lt;code&gt;~/.zshrc&lt;/code&gt; file, comment out the line that sets &lt;code&gt;ZSH_THEME&lt;/code&gt; on line  11 (we will be using Oh My Posh theme, not Oh My Zsh), then below on line 73, add the &lt;code&gt;zsh-autosuggestions&lt;/code&gt; plugin to &lt;code&gt;oh-my-zsh&lt;/code&gt; plugins:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins=(
  git
  zsh-autosuggestions
)
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save the changes and verify that autosuggestions are working (you need to have something in your history first, so type a couple of commands in Windows Terminal, exit with &lt;code&gt;logout&lt;/code&gt;, then start the Terminal again). NOTE: On first run, &lt;code&gt;~/.zcompdump&lt;/code&gt; file will be created, so it is normal for Terminal to start a bit slower.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Grab the &lt;a href="https://github.com/goranvasic/gocilla-oh-my-posh/blob/main/gocilla.omp.json"&gt;Gocilla theme&lt;/a&gt; for &lt;code&gt;Oh My Posh&lt;/code&gt; and save the file under &lt;code&gt;oh-my-posh&lt;/code&gt; themes:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsLo&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/AppData/Local/Programs/oh-my-posh/themes/gocilla.omp.json https://raw.githubusercontent.com/goranvasic/gocilla-oh-my-posh/main/gocilla.omp.json
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Navigate to your Windows &lt;code&gt;%USERPROFILE%&lt;/code&gt; directory, and open the &lt;code&gt;.zshrc&lt;/code&gt; file one more time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;

&lt;p&gt;Add the following line below the &lt;code&gt;source $ZSH/oh-my-zsh.sh&lt;/code&gt; line:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;oh-my-posh init zsh &lt;span class="nt"&gt;--config&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/AppData/Local/Programs/oh-my-posh/themes/gocilla.omp.json&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Restart Windows Terminal and verify that everything is working properly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it. Hopefully this works on your side. You can run this customized Zsh in IntelliJ or VS Code by setting the built-in terminal to open &lt;code&gt;"C:\Program Files\Git\usr\bin\zsh.exe" -il&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can find the latest version of these instructions on my GitHub repo &lt;a href="https://github.com/goranvasic/gocilla-oh-my-posh"&gt;here&lt;/a&gt;. Any comments or suggestions for improvement will be much appreciated.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Python Exceptions</title>
      <dc:creator>Goran Vasic</dc:creator>
      <pubDate>Sat, 27 Apr 2024 16:39:09 +0000</pubDate>
      <link>https://dev.to/goranvasic/python-exceptions-4e9h</link>
      <guid>https://dev.to/goranvasic/python-exceptions-4e9h</guid>
      <description>&lt;p&gt;An &lt;code&gt;Exception&lt;/code&gt; is a special type of object in Python, and Python has many &lt;a href="https://docs.python.org/3/library/exceptions.html"&gt;built-in exception types&lt;/a&gt;. All exceptions must be instances of a class that derives from &lt;a href="https://docs.python.org/3/library/exceptions.html#BaseException"&gt;BaseException&lt;/a&gt;, which means that Python exceptions form a &lt;a href="https://docs.python.org/3/library/exceptions.html#exception-hierarchy"&gt;hierarchy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To &lt;strong&gt;raise an exception&lt;/strong&gt;, means to &lt;strong&gt;start an exception event flow&lt;/strong&gt;. Exception handling is interacting with an exception flow in some manner. An &lt;strong&gt;unhandled exception&lt;/strong&gt; is an exception flow that is not handled by your code, and generally it means that your program will terminate abruptly.&lt;/p&gt;

&lt;p&gt;There are several built-in functions you can use to inspect the exceptions:&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="c1"&gt;# Create an exception object
&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An unexpected value has been provided.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Inspect an exception
&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; ValueError
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; An unexpected value has been provided.
&lt;/span&gt;&lt;span class="nf"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# -&amp;gt; ValueError("An unexpected value has been provided.")
&lt;/span&gt;
&lt;span class="c1"&gt;# Raise an exception
&lt;/span&gt;&lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  LBYL vs EAFP
&lt;/h2&gt;

&lt;p&gt;Something that is "exceptional" should be infrequent. If we are dividing two integers in a loop that repeats 1.000 times, and if, out of every 1.000 we run, we expect division by zero to occur 5 times, we might have 2 approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LBYL (Look Before You Leap)&lt;/strong&gt; – Test that divisor is non-zero 1.000 times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EAFP (Easier to Ask Forgiveness than Permission)&lt;/strong&gt; – Just do it, and handle the division by zero error 5 times (this is often more efficient).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, trying to fully determine if something is going to go wrong is a lot harder to write than just handling things when they do go wrong.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Read the &lt;a href="https://codingnomads.com/look-before-you-leap"&gt;Look Before You Leap&lt;/a&gt; article for more info on LBYL and EAFP approaches for exceptions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Optimizing Performance with Exceptions
&lt;/h2&gt;

&lt;p&gt;In some cases, relying on exceptions can help you improve your code performance. Consider the following Python code:&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;timeit&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&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;1_000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;while&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;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;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;# Calling the len() function in each iteration
&lt;/span&gt;        &lt;span class="n"&gt;l&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="nf"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;process()&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;globals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 40.69522000011057
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue with this code is that it checks the length of the list by calling Python's built-in function &lt;code&gt;len()&lt;/code&gt; at every iteration.&lt;/p&gt;

&lt;p&gt;A significant performance improvement can be achieved by using the &lt;code&gt;for&lt;/code&gt; loop, which checks the length of the list only once:&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;timeit&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&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;1_000&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;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;l&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt; &lt;span class="c1"&gt;# Calling the len() function once
&lt;/span&gt;        &lt;span class="n"&gt;l&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="nf"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;process()&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;globals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 25.074866899987683
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the code executes almost 50% faster (25s compared to previous 40s). The issue here is that the &lt;code&gt;process()&lt;/code&gt; function is again being called &lt;code&gt;500.000&lt;/code&gt; times by the &lt;code&gt;timeit()&lt;/code&gt; function, and the &lt;code&gt;process()&lt;/code&gt; function still invokes the &lt;code&gt;len()&lt;/code&gt; built-in function at every iteration.&lt;/p&gt;

&lt;p&gt;A better solution turns out to be using the &lt;code&gt;try-except&lt;/code&gt; block, where you simply ignore the &lt;code&gt;IndexError&lt;/code&gt; exception that gets raised if the &lt;code&gt;pop()&lt;/code&gt; method is called on an empty list:&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;timeit&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;timeit&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&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;1_000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;l&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="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;IndexError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="c1"&gt;# Ignore the exception
&lt;/span&gt;
&lt;span class="nf"&gt;timeit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;process()&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;globals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 18.16189290001057
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this approach the same code takes only 18 seconds to execute. It is worth mentioning that you should always target a specific exception – in this case &lt;code&gt;IndexError&lt;/code&gt;, not &lt;code&gt;Exception&lt;/code&gt;, which is too broad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Your Own Exceptions
&lt;/h2&gt;

&lt;p&gt;In Python you can define your own custom exceptions:&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="c1"&gt;# Define a custom exception class
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyCustomException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A custom exception occurred&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Check if MyCustomException is a subclass of Exception
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;issubclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyCustomException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# True
&lt;/span&gt;
&lt;span class="c1"&gt;# Example usage of the custom exception:
&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;MyCustomException&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;MyCustomException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Caught exception #1: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Caught exception #1: A custom exception occurred
&lt;/span&gt;
&lt;span class="c1"&gt;# Example usage of the custom exception with different error message:
&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;MyCustomException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is a custom exception&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;MyCustomException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Caught exception #2: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Caught exception #2: This is a custom exception
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;try-except-else-finally&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In combination with the &lt;code&gt;try-except&lt;/code&gt; block, Python's syntax allows you to use the &lt;code&gt;else&lt;/code&gt; clause that executes only if the &lt;code&gt;try-except&lt;/code&gt; block was successful, and the &lt;code&gt;finally&lt;/code&gt; clause that is always executed, so you can use it to ensure that certain tasks are performed if your application terminates abruptly:&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="c1"&gt;# No exceptions raised
&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;4&lt;/span&gt;
&lt;span class="n"&gt;y&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;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;z&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;/&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ZeroDivisionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ELSE: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; / &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FINALLY: Perform some tasks...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# ELSE: 4 / 2 = 2.0
# FINALLY: Perform some tasks...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Dividing by zero raises ZeroDivisionError
&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;4&lt;/span&gt;
&lt;span class="n"&gt;y&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;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;z&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;/&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ZeroDivisionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; / &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Perform some tasks...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# FINALLY: Perform some tasks...
# ---------------------------------------------------------------------------
# ZeroDivisionError                         Traceback (most recent call last)
# Cell In[9], line 5
#       2 y = 0
#       4 try:
# ----&amp;gt; 5     z = x / y
#       6 except ZeroDivisionError:
#       7     raise
# 
# ZeroDivisionError: division by zero
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Using Git on the Command Line</title>
      <dc:creator>Goran Vasic</dc:creator>
      <pubDate>Sat, 26 Sep 2020 08:36:00 +0000</pubDate>
      <link>https://dev.to/goranvasic/using-git-on-the-command-line-1hl4</link>
      <guid>https://dev.to/goranvasic/using-git-on-the-command-line-1hl4</guid>
      <description>&lt;p&gt;&lt;em&gt;This article dives into the more advanced Git topics, providing valuable tips and tricks for using Git on the command line. By going through concrete examples, you will become more confident while working on the command line, greatly increasing overall productivity in your daily job.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Git?
&lt;/h1&gt;

&lt;p&gt;Git is, by far, the most widely used free and open source modern distributed version control system (VCS), an efficient and trustworthy tool that helps you keep track of all the changes in your source code during software development.&lt;/p&gt;

&lt;p&gt;It was initially developed by &lt;a href="https://github.com/torvalds"&gt;Linus Torvalds&lt;/a&gt; in 2005, for development of the Linux kernel, and with significant help from other developers such as &lt;a href="https://github.com/gitster"&gt;Junio Hamano&lt;/a&gt;, it is still an actively maintained project on &lt;a href="https://github.com/git/git"&gt;GitHub&lt;/a&gt;. From the early stages, Git was designed to handle both small and very large projects with speed and efficiency, and since then, it has become a de facto standard tool of its kind.&lt;/p&gt;

&lt;h1&gt;
  
  
  GUI vs Command Line
&lt;/h1&gt;

&lt;p&gt;In spite of its popularity, Git is often criticized for being difficult to learn, primarily due to its command line nature which makes it hard for new users to become familiar with all of the commands and options Git has to offer. This is the main reason why a lot of developers, soon after being introduced to Git, start looking for a GUI client, convinced that it will make them faster and more productive. And it often does, at least in the beginning, as there are a lot of modern third-party tools that offer great user experience and cutting edge features, such as &lt;a href="https://desktop.github.com/"&gt;GitHub Desktop&lt;/a&gt;, &lt;a href="https://www.syntevo.com/smartgit/"&gt;SmartGit&lt;/a&gt;, &lt;a href="https://www.gitkraken.com/"&gt;GitKraken&lt;/a&gt; or &lt;a href="https://www.git-tower.com/mac"&gt;Git Tower&lt;/a&gt;, to name a few.&lt;/p&gt;

&lt;p&gt;The problem is that in the long run, instead of investing their time into learning Git, developers become dependent on these GUI clients and fail miserably the very first moment they have to act quickly from command line, without having the right tool at their disposal. That is why it is always a good idea to take it one step at a time and to practice Git from command line first, because over time, it will make you feel more comfortable and confident while using Git from terminal, greatly increasing productivity in your daily job. In other words, if you wish to become a Git master, you will have to go back to basics and build up from there.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using aliases
&lt;/h1&gt;

&lt;p&gt;One of the very first things we all probably did using Git was setting up our name and email address. It is your first day at a new job, and the colleague sitting next to you tells you that the best way to configure Git is by passing the &lt;code&gt;--global&lt;/code&gt; option, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &lt;span class="s2"&gt;"Your Name"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email &lt;span class="s2"&gt;"your.email@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If this was the first and last time you've used the &lt;code&gt;config&lt;/code&gt; command, there is a chance that you are unaware of the fact that Git can be configured on three levels: &lt;em&gt;local&lt;/em&gt;, &lt;em&gt;global&lt;/em&gt; and &lt;em&gt;system&lt;/em&gt;. Since "local" is the default option, you do not have to specify &lt;code&gt;--local&lt;/code&gt; when invoking the &lt;code&gt;git config&lt;/code&gt; command from your repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--local&lt;/span&gt; user.name &lt;span class="s2"&gt;"Your Name"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git config user.email &lt;span class="s2"&gt;"your.email@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This command will create a "config" file under your &lt;code&gt;$REPO/.git&lt;/code&gt; directory, after which it will take precedence over &lt;code&gt;--global&lt;/code&gt; setting for every value it contains.&lt;/p&gt;

&lt;p&gt;This becomes extremely useful as soon as you have to start working on 2 separate projects, where one of the repositories requires that you configure your corporate email, and the other one your client's email address.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In practice, it is completely fine to configure most of the Git settings on a global level, but it is worth remembering that each Git configuration level overrides values in the "upper" level:&lt;/em&gt;&lt;br&gt;
&lt;code&gt;local &amp;gt; global &amp;gt; system&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Global configuration level is usually more suitable for creating aliases that can replace specific commands which are used often, but are long and cumbersome to type. For example, Git's &lt;code&gt;log&lt;/code&gt; command offers a lot of information by default, but it can be rather difficult to get the high-level overview of all commit messages, which is what we usually want. For this reason, most people often use &lt;code&gt;git log&lt;/code&gt; with some additional options, in order to simplify the output or to limit the number of results, e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;-n10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But we can take this a step further, and instead of constantly typing the &lt;code&gt;--oneline&lt;/code&gt; option or limiting the number of results to 10, we can specify the exact kind of information we need by globally configuring a &lt;code&gt;hist&lt;/code&gt; alias that will show us the last 10 commits accompanied by a nice graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.hist &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"log --graph --date=short --abbrev=10 &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  --format='%C(yellow)%h %C(white)%ad %C(green)%s %C(cyan)[%an, %ar]%C(white)%d' &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  -n10"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I know that this might scare you at first, so try removing the "format" part from the command to make it more readable.&lt;/p&gt;

&lt;p&gt;Executing this command will allow us to use the &lt;code&gt;hist&lt;/code&gt; alias to display the latest 10 commits from Git history. We can even override the number of displayed commits to show the last 20 commits, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git hist &lt;span class="nt"&gt;-n20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Overriding specific parameters is certainly useful, but it is worth noting that Git allows you to pass parameters to an alias:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.echo &lt;span class="s1"&gt;'!f() { text=${1-Hello World}; echo $text; }; f'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Again, the example above might seem confusing at first, but if you focus only on the part between the quotation marks, you will see that we are defining an anonymous function by specifying its body between curly braces, and we are then invoking it. Individual commands are separated by semicolons, and we have defined a variable "text" which takes the first parameter or defaults to "Hello World" if the parameter has not been passed. The function then prints value of variable "text" to the console using standard system command &lt;code&gt;echo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As you can see, this enables us to write powerful functions that accept one or more parameters, and by utilizing both Git and OS level commands, you can easily create custom Git plug-ins that may be used by your entire team for some specific tasks.&lt;/p&gt;

&lt;p&gt;We can try out this concept by defining the &lt;code&gt;find&lt;/code&gt; alias that will allow us to quickly search for a particular commit message using case-insensitive text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.find &lt;span class="s1"&gt;'!f() { \
  text=${1}; \
  results=${2-10}; \
  git log --all --full-history --oneline -n$results \
  -i --grep="$text"; \
  }; f'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, by using the following command, we can search through all commit messages that contain a specific word, such as "refactor", limiting output to only 5 results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git find &lt;span class="s2"&gt;"refactor"&lt;/span&gt; 5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Reset
&lt;/h1&gt;

&lt;p&gt;One of the things that often make beginners uncomfortable (perhaps even scared) while using Git is its tendency to keep track of all the file changes in a repository. In other words, even if you only wish to compile the project without modifying any code, Git is still going to detect all artifacts produced after compilation and report that there are new files present in your repository.&lt;/p&gt;

&lt;p&gt;Manually deleting files or adding them to &lt;code&gt;.gitignore&lt;/code&gt; is often the easiest or quickest solution, but if there are a lot of random untracked files in your working directory, you should be aware of the following command which helps you clean-up dirty working tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clean &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the command above, parameter &lt;code&gt;-f&lt;/code&gt; means "force", and it will remove any untracked files, as well as any subdirectories that become empty as a result.&lt;/p&gt;

&lt;p&gt;You should not worry about losing any changes on your existing files, they will remain intact. On the other hand, in a situation where you would like to revert all changes performed on tracked files while leaving the untracked files as they were, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; HEAD
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can omit &lt;code&gt;HEAD&lt;/code&gt; because it is implied, and it is not mandatory to use uppercase letters. Finally, if you wish to undo all of your changes, you can reset the entire working directory to the state of the latest commit by adding all files in the working directory to the staging area first, and then performing a hard reset on them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git reset &lt;span class="nt"&gt;--hard&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Undo
&lt;/h1&gt;

&lt;p&gt;Having an "undo" option in software is such a common feature these days that we often end up shocked once we realize that it is not available. Valuable data can be lost and irreversible damage can be made. This is one of the main reasons why beginners hesitate so much when someone asks them to commit their changes in Git. What if they have just made a huge mistake, and there is no way back?&lt;/p&gt;

&lt;p&gt;The good news is that you can revert your changes even after committing them, the same way as you can revert all changes to your tracked or untracked files. The only difference this time is that, instead of referencing the last commit using &lt;code&gt;HEAD&lt;/code&gt;, you should perform a hard reset to a previous commit, which can be referenced using &lt;code&gt;HEAD^&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; HEAD^
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There is a more convenient notation for referencing one or more commits, such as &lt;code&gt;HEAD~1&lt;/code&gt;, &lt;code&gt;HEAD~2&lt;/code&gt; etc. This way of undoing changes almost feels like you are peeling the layers of an onion. But what if, instead of completely removing a layer, you only wish to change (update) the last commit? You can step back and re-commit your changes by performing a soft reset to a previous commit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git reset &lt;span class="nt"&gt;--soft&lt;/span&gt; HEAD~1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Similar result can also be achieved by amending previous commit. In a situation when you forget to add some important files to a commit you've already created, or if there are some changes that logically belong to a previous commit, it is a better route to modify the existing commit by adding these changes to staging area, and then committing them using the &lt;code&gt;--amend&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git commit &lt;span class="nt"&gt;--amend&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Git will prompt you to update the old commit message, after which it will replace the old commit with a new one. This new commit will also get a unique hash, as a result of containing both old and new changes, so it is important to note that undoing or modifying your commit history is fine as long as you haven't published the old commit history to a remote repository.&lt;/p&gt;

&lt;p&gt;In case that you did, Git will refuse to overwrite your remote repository's commit history and will warn you as soon as you try to push your newest changes. At this point, you should coordinate with your team members, because some of your colleagues might have already pulled your previous changes and started working on top of them.&lt;/p&gt;

&lt;p&gt;You can imagine how problematic this can become when you have a large team of developers contributing to the same repository. That is why, in these type of situations, it is always better to revert a particular commit using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git revert &amp;lt;commit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Reverting a commit will not modify the existing commit history – it will create a new commit on top of it. This new commit will do the complete opposite of all of the changes performed in a referenced commit, so it is completely safe to push it to your remote.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reflog
&lt;/h1&gt;

&lt;p&gt;By now, you should already feel more comfortable using Git. At least, you should no longer be afraid of creating new commits, knowing how easy it is to undo all of your changes. Actually, you should start committing more frequently, because now you know that you can always reset or modify a commit, but if you perform a hard reset on any uncommitted changes, they are lost for good. As a matter of fact, the only way that you can completely lose your changes in Git is by NOT committing them, because even if you perform a hard reset to &lt;code&gt;HEAD~4&lt;/code&gt;, you can always go back.&lt;/p&gt;

&lt;p&gt;This is possible because Git keeps a local journal of everything you’ve done in your repository after cloning it. This journal is called "reflog", and it allows you to see all of the actions you've performed on a particular branch by using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git reflog &amp;lt;branch-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If branch is not specified, &lt;code&gt;HEAD&lt;/code&gt; is implied. Reflog also preserves the order in which you've performed all actions, with &lt;code&gt;HEAD@{0}&lt;/code&gt; being the most recent one, and &lt;code&gt;HEAD@{1}&lt;/code&gt; the one before it. This way, even if you undo the last 4 commits by hard resetting to &lt;code&gt;HEAD~4&lt;/code&gt;, you can always undo that step by performing a hard reset to &lt;code&gt;HEAD@{1}&lt;/code&gt;. What's more, if you perform a hard reset to &lt;code&gt;HEAD@{1}&lt;/code&gt; one more time, it will again remove the last 4 commits because this was the last action you did before performing an undo. Using &lt;code&gt;reflog&lt;/code&gt; for undoing your actions is so convenient that it simply deserves its own alias. The following command creates an alias &lt;code&gt;undo&lt;/code&gt; which performs a hard reset to a previous action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; alias.undo &lt;span class="s1"&gt;'!f() { \
  git reset --hard $(git rev-parse --abbrev-ref HEAD)@{${1-1}}; \
  }; f'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, you can simply type &lt;code&gt;git undo&lt;/code&gt; whenever you hard reset to a particular commit.&lt;/p&gt;

&lt;h1&gt;
  
  
  Working with branches
&lt;/h1&gt;

&lt;p&gt;It is possible that you have been in a situation where your fellow developer is unable to perform a quick bug fix because he/she is currently on a separate branch, working on a specific feature, and current code changes are half-done and not ready to be committed. This the right time to introduce them to &lt;code&gt;git stash&lt;/code&gt;. Stashing takes your modified tracked files and staged changes and saves it on a stack of unfinished changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git stash save &amp;lt;comment&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can then checkout another branch, fix the bug, and reapply your stashed uncommitted changes to a previous branch or anywhere you want using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git stash apply stash@&lt;span class="o"&gt;{&lt;/span&gt;0&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To view all stashed items, use &lt;code&gt;git stash list&lt;/code&gt;, and to apply and remove the latest stashed item from the stack, use &lt;code&gt;git stash pop&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There is one more situation which might slow you down, and that is when your code has a dependency on a particular commit that has been published to the remote repo. The only problem is that you are on a separate branch and do not want to merge all of the changes that came before and after that commit. You can easily solve this problem using Git's &lt;code&gt;cherry-pick&lt;/code&gt; feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git cherry-pick &amp;lt;commit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will take a particular commit that exists on a separate branch and copy it on top of your branch. It's content will be exactly the same as in the original commit, but it will have a different SHA-1 hash.&lt;/p&gt;

&lt;h1&gt;
  
  
  Fixing merge conflicts
&lt;/h1&gt;

&lt;p&gt;Copying code from other branches or merging your branch with another one can often result in merge conflicts. This happens when both branches contain commits that are changing the same code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nE4W2Q4p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h973slo0gr8mem11hmjr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nE4W2Q4p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h973slo0gr8mem11hmjr.png" alt="Merge conflict"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Logically, Git will ask you to choose which changes to keep. The easiest way to resolve conflicts is by keeping either your or their changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout &lt;span class="nt"&gt;--ours&lt;/span&gt; &amp;lt;file&amp;gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout &lt;span class="nt"&gt;--theirs&lt;/span&gt; &amp;lt;file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The other way is to manually edit all files that were modified by both sides. Git has a fairly unknown feature called Reuse Recorded Resolution (ReReRe):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; rerere.enabled &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It allows you to ask Git to remember how you’ve resolved a hunk conflict so that the next time it sees the same conflict, Git can automatically resolve it for you.&lt;/p&gt;

&lt;h1&gt;
  
  
  Rewriting history
&lt;/h1&gt;

&lt;p&gt;Another way of solving the problem with merge conflicts is to resolve them on your branch before you even create a pull request. Git’s &lt;code&gt;pull --rebase&lt;/code&gt; allows you to avoid creating merge commits, thus making Git history appear linear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git pull origin develop &lt;span class="nt"&gt;--rebase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Invoking this command will temporarily remove your code changes and apply the latest changes that have been published to &lt;code&gt;develop&lt;/code&gt; branch, simulating a scenario where you have just created a new branch from the latest &lt;code&gt;develop&lt;/code&gt;. Then, one after another, it will try to add all of your commits back, stopping whenever a merge conflict occurs. After fixing a potential conflict, you should continue the process by typing &lt;code&gt;git rebase --continue&lt;/code&gt;. Eventually, you should end up having the latest changes from "develop", followed by all of your "conflict-free" commits.&lt;/p&gt;

&lt;p&gt;Pulling with &lt;code&gt;--rebase&lt;/code&gt; is such a common workflow that there is a dedicated configuration option for it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; branch.autosetuprebase always
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Another way of rewriting history is by using Git's interactive rebase feature. Among other things, it allows you to reorder, rename, fix, drop or squash commits from your local history:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git rebase &lt;span class="nt"&gt;-i&lt;/span&gt; &amp;lt;parent-commit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Again, after fixing a potential conflict, simply run &lt;code&gt;git rebase --continue&lt;/code&gt;. Also make sure not to rebase already published commit history, do this only on your local changes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Git hooks
&lt;/h1&gt;

&lt;p&gt;Git allows you to enforce code quality on your project using Git hooks. All hooks are scripts, stored in the &lt;code&gt;.git/hooks&lt;/code&gt; subdirectory of the Git repository. You can use existing sample scripts by removing ".sample" suffix from their name, or write your own, such as "&lt;a href="http://git.io/validate-commit-msg"&gt;http://git.io/validate-commit-msg&lt;/a&gt;".&lt;/p&gt;

&lt;p&gt;Git hook from the example above will warn you if your commit message is longer than 50 characters, and will ask you to modify the message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GSlZ6oST--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p5qbganpzkl508tv7nhe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GSlZ6oST--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/p5qbganpzkl508tv7nhe.png" alt="Git hooks"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another example could be setting up a server-side hook that gets triggered whenever you push code to your remote repo. It will read all commit messages, and automatically resolve a particular JIRA using a plugin whenever it detects the word "Fix" accompanied by a JIRA number. It is worth mentioning that client-side hooks are not copied when you clone a repository. If your intent with these scripts is to enforce a policy, you'll probably want to do that on the server side.&lt;/p&gt;

</description>
      <category>git</category>
      <category>terminal</category>
      <category>linux</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
