<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Blog — George Mishurovsky: posts tagged git</title>
<link>https://mishurovsky.com/blog/?go=tags/git/</link>
<description>A blog by George Mishurovsky — a senior software engineer with a medical degree. Drawing from both engineering and scientific thinking, he explores software, architecture, design, psychology, and product thinking.</description>
<author></author>
<language>en</language>
<generator>Aegea 11.3 (v4134e)</generator>

<itunes:owner>
<itunes:name></itunes:name>
<itunes:email>george@mishurovsky.com</itunes:email>
</itunes:owner>
<itunes:subtitle>A blog by George Mishurovsky — a senior software engineer with a medical degree. Drawing from both engineering and scientific thinking, he explores software, architecture, design, psychology, and product thinking.</itunes:subtitle>
<itunes:image href="https://mishurovsky.com/blog/pictures/userpic/userpic-square@2x.jpg?1753619610" />
<itunes:explicit>no</itunes:explicit>

<item>
<title>How to Add Version Control Info to zsh Prompt</title>
<guid isPermaLink="false">53</guid>
<link>https://mishurovsky.com/blog/?go=all/how-to-add-version-control-info-to-zsh-prompt/</link>
<pubDate>Mon, 31 Aug 2026 11:33:01 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/how-to-add-version-control-info-to-zsh-prompt/</comments>
<description>
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://mishurovsky.com/blog/pictures/vcs-in-zsh@2x.png" width="1287" height="668" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;MacOS default shell, &lt;span class="inline-code"&gt;zsh&lt;/span&gt;, comes with a neat version control system integration. It works not only with &lt;span class="inline-code"&gt;git&lt;/span&gt;, but also with &lt;span class="inline-code"&gt;svn&lt;/span&gt;, &lt;span class="inline-code"&gt;mercurial&lt;/span&gt;, and many others! The capabilities are quite extensive — you can see yourself in &lt;a href="https://zsh.sourceforge.io/Doc/Release/User-Contributions.html#SEC273"&gt;zsh manual&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;One thing that I found always missing from default terminal views into folders was if the folder is part of some git repo and which branch is currently checked out. Turns out, about 10 lines of &lt;span class="inline-code"&gt;.zshrc&lt;/span&gt; is enough to provide not only that, but also whether the current branch contains changes, staged and unstaged! I am sharing a script for &lt;span class="inline-code"&gt;zsh&lt;/span&gt; and its alternative for &lt;span class="inline-code"&gt;bash&lt;/span&gt;, which does not have a VCS integration and thus relies on native &lt;span class="inline-code"&gt;git&lt;/span&gt; commands. The result is branch name with &lt;span class="inline-code"&gt;+&lt;/span&gt; and &lt;span class="inline-code"&gt;*&lt;/span&gt; markers appended to the end of folder path, whenever the folder belongs to some git repository.&lt;/p&gt;
&lt;h2&gt;Zsh&lt;/h2&gt;
&lt;div class="e2-code-block" data-language="sh"&gt;&lt;div class="e2-code-header"&gt;&lt;span class="e2-code-language"&gt;Shell&lt;/span&gt;&lt;button class="e2-code-copy" type="button" aria-label="Copy code to clipboard" data-copy-text="Copy" data-copied-text="Copied!" data-failed-text="Failed"&gt;&lt;span class="e2-svgi"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"&gt;&lt;mask id="cutout"&gt;&lt;rect width="100%" height="100%" fill="white"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" stroke-width="1.33" rx="1" fill="black" stroke="black"/&gt;&lt;/mask&gt;&lt;rect x="5.25" y="1.75" width="9" height="9" rx="1" stroke-width="1.33" fill="none" mask="url(#cutout)"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" rx="1" stroke-width="1.33" fill="none"/&gt;&lt;/svg&gt;
&lt;/span&gt;Copy&lt;/button&gt;&lt;/div&gt;&lt;pre&gt;&lt;code class="hljs language-sh"&gt;# Always display version control info in the prompt
autoload -Uz vcs_info
autoload -Uz add-zsh-hook
add-zsh-hook precmd vcs_info

zstyle &amp;#039;:vcs_info:*&amp;#039; check-for-changes true
zstyle &amp;#039;:vcs_info:git:*&amp;#039; unstagedstr &amp;#039;%F{red}*%f&amp;#039;
zstyle &amp;#039;:vcs_info:git:*&amp;#039; stagedstr &amp;#039;%F{green}+%f&amp;#039;
zstyle &amp;#039;:vcs_info:git:*&amp;#039; formats &amp;#039; %F{cyan}[%b%u%c%F{cyan}]%f&amp;#039;

setopt PROMPT_SUBST
PROMPT=&amp;#039;%~${vcs_info_msg_0_} %# &amp;#039;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;Bash&lt;/h2&gt;
&lt;div class="e2-code-block" data-language="sh"&gt;&lt;div class="e2-code-header"&gt;&lt;span class="e2-code-language"&gt;Shell&lt;/span&gt;&lt;button class="e2-code-copy" type="button" aria-label="Copy code to clipboard" data-copy-text="Copy" data-copied-text="Copied!" data-failed-text="Failed"&gt;&lt;span class="e2-svgi"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"&gt;&lt;mask id="cutout"&gt;&lt;rect width="100%" height="100%" fill="white"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" stroke-width="1.33" rx="1" fill="black" stroke="black"/&gt;&lt;/mask&gt;&lt;rect x="5.25" y="1.75" width="9" height="9" rx="1" stroke-width="1.33" fill="none" mask="url(#cutout)"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" rx="1" stroke-width="1.33" fill="none"/&gt;&lt;/svg&gt;
&lt;/span&gt;Copy&lt;/button&gt;&lt;/div&gt;&lt;pre&gt;&lt;code class="hljs language-sh"&gt;COLOR_CYAN=&amp;#039;\e[36m&amp;#039;
COLOR_RED=&amp;#039;\e[31m&amp;#039;
COLOR_GREEN=&amp;#039;\e[32m&amp;#039;
COLOR_RESET=&amp;#039;\e[0m&amp;#039;

__git_prompt() {
    local branch

    # If not a Git repository
    branch=$(git symbolic-ref --short HEAD 2&amp;gt;/dev/null) ||
        branch=$(git rev-parse --short HEAD 2&amp;gt;/dev/null) ||
        return

    GIT_PROMPT=&amp;quot;${COLOR_CYAN}[${branch}&amp;quot;

    # Staged changes
    if ! git diff --cached --quiet 2&amp;gt;/dev/null; then
        GIT_PROMPT+=&amp;quot;${COLOR_GREEN}+${COLOR_CYAN}&amp;quot;
    fi

    # Unstaged changes
    if ! git diff --quiet 2&amp;gt;/dev/null; then
        GIT_PROMPT+=&amp;quot;${COLOR_RED}*${COLOR_CYAN}&amp;quot;
    fi

    GIT_PROMPT+=&amp;quot;]${COLOR_RESET}&amp;quot;
}

__update_prompt() {
    GIT_PROMPT=&amp;quot;&amp;quot;
    __git_prompt
    PS1=&amp;#039;\w &amp;#039;&amp;quot;${GIT_PROMPT}&amp;quot;&amp;#039; \$ &amp;#039;
}

PROMPT_COMMAND=&amp;quot;__update_prompt${PROMPT_COMMAND:+;$PROMPT_COMMAND}&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
</item>

<item>
<title>How to Delete All Local Git Branches in One Command</title>
<guid isPermaLink="false">11</guid>
<link>https://mishurovsky.com/blog/?go=all/how-to-delete-all-local-git-branches/</link>
<pubDate>Thu, 28 Aug 2025 13:46:06 +0200</pubDate>
<author></author>
<comments>https://mishurovsky.com/blog/?go=all/how-to-delete-all-local-git-branches/</comments>
<description>
&lt;p&gt;First, checkout to main (or any other branch you want to clear from upstream branches).&lt;/p&gt;
&lt;p&gt;Now, let’s build the command, step by step.&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Check which branches were merged to the current branch:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-code-block" data-language="sh"&gt;&lt;div class="e2-code-header"&gt;&lt;span class="e2-code-language"&gt;Shell&lt;/span&gt;&lt;button class="e2-code-copy" type="button" aria-label="Copy code to clipboard" data-copy-text="Copy" data-copied-text="Copied!" data-failed-text="Failed"&gt;&lt;span class="e2-svgi"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"&gt;&lt;mask id="cutout"&gt;&lt;rect width="100%" height="100%" fill="white"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" stroke-width="1.33" rx="1" fill="black" stroke="black"/&gt;&lt;/mask&gt;&lt;rect x="5.25" y="1.75" width="9" height="9" rx="1" stroke-width="1.33" fill="none" mask="url(#cutout)"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" rx="1" stroke-width="1.33" fill="none"/&gt;&lt;/svg&gt;
&lt;/span&gt;Copy&lt;/button&gt;&lt;/div&gt;&lt;pre&gt;&lt;code class="hljs language-sh"&gt;git branch --merged&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="2"&gt;
&lt;li&gt;Filter out current branch from the output – it is marked by an asterisk (*):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-code-block" data-language="sh"&gt;&lt;div class="e2-code-header"&gt;&lt;span class="e2-code-language"&gt;Shell&lt;/span&gt;&lt;button class="e2-code-copy" type="button" aria-label="Copy code to clipboard" data-copy-text="Copy" data-copied-text="Copied!" data-failed-text="Failed"&gt;&lt;span class="e2-svgi"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"&gt;&lt;mask id="cutout"&gt;&lt;rect width="100%" height="100%" fill="white"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" stroke-width="1.33" rx="1" fill="black" stroke="black"/&gt;&lt;/mask&gt;&lt;rect x="5.25" y="1.75" width="9" height="9" rx="1" stroke-width="1.33" fill="none" mask="url(#cutout)"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" rx="1" stroke-width="1.33" fill="none"/&gt;&lt;/svg&gt;
&lt;/span&gt;Copy&lt;/button&gt;&lt;/div&gt;&lt;pre&gt;&lt;code class="hljs language-sh"&gt;git branch --merged | grep -v \*&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="3"&gt;
&lt;li&gt;Turn the columnar output into a space-separated string:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-code-block" data-language="sh"&gt;&lt;div class="e2-code-header"&gt;&lt;span class="e2-code-language"&gt;Shell&lt;/span&gt;&lt;button class="e2-code-copy" type="button" aria-label="Copy code to clipboard" data-copy-text="Copy" data-copied-text="Copied!" data-failed-text="Failed"&gt;&lt;span class="e2-svgi"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"&gt;&lt;mask id="cutout"&gt;&lt;rect width="100%" height="100%" fill="white"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" stroke-width="1.33" rx="1" fill="black" stroke="black"/&gt;&lt;/mask&gt;&lt;rect x="5.25" y="1.75" width="9" height="9" rx="1" stroke-width="1.33" fill="none" mask="url(#cutout)"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" rx="1" stroke-width="1.33" fill="none"/&gt;&lt;/svg&gt;
&lt;/span&gt;Copy&lt;/button&gt;&lt;/div&gt;&lt;pre&gt;&lt;code class="hljs language-sh"&gt;git branch --merged | grep -v \* | xargs&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol start="4"&gt;
&lt;li&gt;Feed these arguments to the deletion command (passed in the second argument of &lt;span class="inline-code"&gt;xargs&lt;/span&gt;):&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-code-block" data-language="sh"&gt;&lt;div class="e2-code-header"&gt;&lt;span class="e2-code-language"&gt;Shell&lt;/span&gt;&lt;button class="e2-code-copy" type="button" aria-label="Copy code to clipboard" data-copy-text="Copy" data-copied-text="Copied!" data-failed-text="Failed"&gt;&lt;span class="e2-svgi"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"&gt;&lt;mask id="cutout"&gt;&lt;rect width="100%" height="100%" fill="white"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" stroke-width="1.33" rx="1" fill="black" stroke="black"/&gt;&lt;/mask&gt;&lt;rect x="5.25" y="1.75" width="9" height="9" rx="1" stroke-width="1.33" fill="none" mask="url(#cutout)"/&gt;&lt;rect x="1.75" y="5.25" width="9" height="9" rx="1" stroke-width="1.33" fill="none"/&gt;&lt;/svg&gt;
&lt;/span&gt;Copy&lt;/button&gt;&lt;/div&gt;&lt;pre&gt;&lt;code class="hljs language-sh"&gt;git branch --merged | grep -v \* | xargs git branch -D&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
</item>


</channel>
</rss>