<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>git on
A Scripter's Notes</title><link>https://scripter.co/tags/git/</link><description>Recent content in git
on A Scripter's Notes</description><language>en-us</language><managingEditor>kaushal.modi@gmail.com (Kaushal Modi)</managingEditor><webMaster>kaushal.modi@gmail.com (Kaushal Modi)</webMaster><lastBuildDate>Mon, 08 Jan 2024 07:42:20 -0500</lastBuildDate><generator>Hugo -- gohugo.io</generator><docs>https://validator.w3.org/feed/docs/rss2.html</docs><atom:link href="https://scripter.co/tags/git/index.xml" rel="self" type="application/rss+xml"/><item><title>Version controlling Jenkins config</title><link>https://scripter.co/version-controlling-jenkins-config/</link><description>&lt;blockquote>Jenkins is an amazing free and open source continuous integration and
deployment software. But its primary means of configuration is a web
UI, and recently that cost me a lot of debug time. That set me down
the path of figuring out a way to version control the Jenkins config
(the &lt;code>$JENKINS_HOME&lt;/code> directory).&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#what-bit-me">What bit me&lt;/a>&lt;/li>
&lt;li>&lt;a href="#dot-gitignore-for-jenkins-config">&lt;code>.gitignore&lt;/code> for Jenkins config&lt;/a>&lt;/li>
&lt;li>&lt;a href="#jenkins-plugin-manager">Jenkins Plugin Manager&lt;/a>&lt;/li>
&lt;li>&lt;a href="#full-solution">Full solution&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>&lt;a href="https://www.jenkins.io/">Jenkins&lt;/a> is a wonderful piece of software and I use it with my
Bitbucket git repos for &lt;a href="https://en.wikipedia.org/wiki/CI/CD">CI/CD&lt;/a>.&lt;/p>
&lt;p>Jenkins uses a web UI for its configuration. I dislike that because
it&amp;rsquo;s difficult to document the configuration process without
screenshots, and if I need to create a new server, it&amp;rsquo;s a manual
process of clicking through tabs and filling in the text boxes. I
didn&amp;rsquo;t mind this enough to do anything about it .. that is until I
finally got bit by it.&lt;/p>
&lt;h2 id="what-bit-me">What bit me&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#what-bit-me">#&lt;/a>&lt;/h2>
&lt;p>Without going into too much detail, that issue was multi-fold:&lt;/p>
&lt;ol>
&lt;li>I had unknowingly messed up the &lt;em>Project-based Matrix Authorization
Strategy&lt;/em> such that other users in my team were not able to view
the Jenkins jobs.&lt;/li>
&lt;li>I had also updated the Jenkins server that introduced a bug
(&lt;a href="https://issues.jenkins.io/browse/JENKINS-68748">JENKINS-68748&lt;/a>) where the &lt;em>Test LDAP Settings&lt;/em> failed with an
error, but the LDAP authentication actually worked!&lt;/li>
&lt;li>I had also updated all the plugins after updating Jenkins. So if I
rolled back the Jenkins versions, most of the plugins would fail
because of incompatibility with the older Jenkins version. I had
updated Jenkins after months!&lt;/li>
&lt;/ol>
&lt;p>That&amp;rsquo;s when I wished that my whole Jenkins was
version-controlled. That would have allowed me to roll back to the
last working &amp;ldquo;Jenkins image&amp;rdquo; with the Jenkin version, plugins'
versions and my Jenkins config all in sync.&lt;/p>
&lt;p>I had delayed doing this because my &lt;code>$JENKINS_HOME&lt;/code> was more than 1GB
in size and I didn&amp;rsquo;t have time or motivation to figure out what stuff
I should commit and what I should ignore .. But no more &amp;mdash; The time
had finally come.&lt;/p>
&lt;h2 id="dot-gitignore-for-jenkins-config">&lt;code>.gitignore&lt;/code> for Jenkins config&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#dot-gitignore-for-jenkins-config">#&lt;/a>&lt;/h2>
&lt;p>So I did what any good engineer would do .. start looking for a
solution online. I found &lt;a href="https://stackoverflow.com/a/4695615">this StackOverflow answer&lt;/a> for &lt;em>Is there a way
to keep Hudson / Jenkins configuration files in source control?&lt;/em>.&lt;/p>
&lt;p>That answer shares a &lt;code>.gitignore&lt;/code> that ignores files not necessary for
configuring a Jenkins server &amp;mdash; Example: job builds, workspace, log
files, etc. But it didn&amp;rsquo;t work out of the box because the plugin
version info wasn&amp;rsquo;t getting committed correctly. I had committed
everything to git after using the suggested &lt;code>.gitignore&lt;/code> and pushed to
my git remote. But if I cloned that repo to a different area and
attempted to start the Jenkins server from there, it crashed with this
message:&lt;/p>
&lt;p>&lt;a id="code-snippet--jenkins-crash-log">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">2022-07-15 13:07:06.082+0000 [id=31] SEVERE jenkins.InitReactorRunner$1#onTaskFailed: Failed Loading global config
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">com.thoughtworks.xstream.mapper.CannotResolveClassException: hudson.security.ProjectMatrixAuthorizationStrategy
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:81)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:79)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.SecurityMapper.realClass(SecurityMapper.java:71)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at hudson.util.XStream2$CompatibilityMapper.realClass(XStream2.java:411)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at hudson.util.xstream.MapperDelegate.realClass(MapperDelegate.java:46)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:47)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at hudson.util.RobustReflectionConverter.determineType(RobustReflectionConverter.java:521)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> at hudson.util.RobustReflectionConverter.doUnmarshal(RobustReflectionConverter.java:346)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Caused: jenkins.util.xstream.CriticalXStreamException:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">---- Debugging information ----
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cause-message : hudson.security.ProjectMatrixAuthorizationStrategy
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">class : hudson.model.Hudson
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">required-type : hudson.model.Hudson
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">converter-type : hudson.util.RobustReflectionConverter
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">path : /hudson/authorizationStrategy
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">line number : 12
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">version : not available
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">-------------------------------
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--jenkins-crash-log">Code Snippet 1&lt;/a>:&lt;/span>
Snippet of Jenkins crash when attempting to run the server from the freshly cloned git repo
&lt;/div>
&lt;h2 id="jenkins-plugin-manager">Jenkins Plugin Manager&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#jenkins-plugin-manager">#&lt;/a>&lt;/h2>
&lt;p>So I &lt;a href="https://community.jenkins.io/t/version-controlling-jenkins-config-help-defining-a-gitignore-that-minimizes-the-git-repo-size/3036">reached out for help&lt;/a> on the Jenkins Community. One of the key
contributors to Jenkins, &lt;a href="https://community.jenkins.io/u/MarkEWaite">Mark Waite&lt;/a>, was tremendously helpful. He
suggested using his &lt;a href="https://github.com/jenkinsci/plugin-installation-manager-tool">&lt;code>jenkins-plugin-manager&lt;/code>&lt;/a> tool. After trying it out
for a bit, I realized that this tool had everything I needed for
version controlling the plugin versions:&lt;/p>
&lt;ul>
&lt;li>Ability to save a list of installed Jenkins plugins and their
versions to a file.&lt;/li>
&lt;li>Ability to batch install all the plugins of the versions listed in a
file.&lt;/li>
&lt;/ul>
&lt;p>This was like doing Python&amp;rsquo;s &lt;a href="https://scripter.co/saving-python-pip-dependencies/">plugin management using
&lt;code>requirements.txt&lt;/code>&lt;/a>, except that this was for Jenkins.&lt;/p>
&lt;h2 id="full-solution">Full solution&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#full-solution">#&lt;/a>&lt;/h2>
&lt;p>With a combination of the &lt;code>.gitignore&lt;/code> that I started with from that
SO answer, managing plugins using &lt;code>jenkins-plugin-manager&lt;/code>, tweaking
the &lt;code>.gitignore&lt;/code> to my liking, and adding helper Bash scripts for
downloading and running Jenkins server binaries, and doing the plugin
management, I finally got what I needed:&lt;/p>
&lt;div class="org-center">
&lt;p>&lt;a href="https://github.com/kaushalmodi/jenkins-minimal">https://github.com/kaushalmodi/jenkins-minimal&lt;/a>&lt;/p>
&lt;/div>
&lt;p>The README on the repo has all the instructions.&lt;/p></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/unix">unix</category><category domain="https://scripter.co/tags/git">git</category><category domain="https://scripter.co/tags/jenkins">jenkins</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/version-controlling-jenkins-config/</guid><pubDate>Wed, 20 Jul 2022 00:18:00 -0400</pubDate></item><item><title>Using Git Delta with Magit</title><link>https://scripter.co/using-git-delta-with-magit/</link><description>&lt;blockquote>&lt;em>Git Delta&lt;/em> is a command line utility that beautifies git diffs in the
terminal. But did you know that it can do the same in Magit too?&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#installing-delta">Installing &lt;code>delta&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#installing-magit-delta">Installing &lt;code>magit-delta&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="#configuring-delta">Configuring &lt;code>delta&lt;/code>&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>&lt;a href="https://github.com/dandavison/delta">Delta&lt;/a> is a highly configurable
&lt;span class="sidenote-number">&lt;small class="sidenote">
I am not kidding. Check out the output of &lt;a href="https://dandavison.github.io/delta/full---help-output.html">&lt;code>delta --help&lt;/code>&lt;/a>.
&lt;/small>&lt;/span>
command line utility that makes the git diffs look better, while also
syntax-highlighting
&lt;span class="sidenote-number">&lt;small class="sidenote">
&lt;a href="https://github.com/Wilfred/difftastic/">Difftastic&lt;/a> is another popular diff tool which compares files based on
their syntax. I like reviewing &lt;em>git diffs&lt;/em> from within Emacs
(Magit). But &lt;em>difftastic&lt;/em> &lt;a href="https://github.com/Wilfred/difftastic/issues/251">does not support Magit&lt;/a>.
&lt;/small>&lt;/span>
the code in the diffs.&lt;/p>
&lt;p>When I first heard of &amp;ldquo;syntax highlighted diffs&amp;rdquo;, I wasn&amp;rsquo;t sure what
that meant. If you are in the same boat, here&amp;rsquo;s a screenshot that
shows that.&lt;/p>
&lt;p>&lt;a id="figure--git-delta-example">&lt;/a>&lt;/p>
&lt;figure>
&lt;a href="delta-example.png">
&lt;img src="https://scripter.co/using-git-delta-with-magit/delta-example.png" alt="Figure 1: Example of how delta renders a git diff for an ox-hugo commit"/> &lt;/a>&lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>Example of how &lt;code>delta&lt;/code> renders a &lt;em>git diff&lt;/em> for an &lt;code>ox-hugo&lt;/code> commit
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;p>But I do most of my git operations including viewing of diffs from
within Emacs, using &lt;a href="https://magit.vc">Magit&lt;/a>.&lt;/p>
&lt;div class="verse">
&lt;p>        .. and thankfully &lt;em>delta&lt;/em> &lt;a href="https://dandavison.github.io/delta/using-delta-with-magit.html">works with Magit&lt;/a>!&lt;br />&lt;/p>
&lt;/div>
&lt;p>Below screenshot shows how the same diff looks like in Magit.&lt;/p>
&lt;p>&lt;a id="figure--git-magit-delta-example">&lt;/a>&lt;/p>
&lt;figure>
&lt;a href="magit-delta-example.png">
&lt;img src="https://scripter.co/using-git-delta-with-magit/magit-delta-example.png" alt="Figure 2: Example of how magit-delta renders a git diff for an ox-hugo commit"/> &lt;/a>&lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 2: &lt;/span>Example of how &lt;code>magit-delta&lt;/code> renders a &lt;em>git diff&lt;/em> for an &lt;code>ox-hugo&lt;/code> commit
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;p>The &lt;a href="https://github.com/dandavison/magit-delta">&lt;code>magit-delta&lt;/code>&lt;/a> Emacs package makes this possible, which is also
developed by the &lt;code>delta&lt;/code> author Dan Davison.&lt;/p>
&lt;dl>
&lt;dt>Caveat&lt;/dt>
&lt;dd>If the line numbers are enabled in &lt;code>delta&lt;/code>, they mess up
the interactive expanding and collapsing of diffs in Magit. See
&lt;a href="https://github.com/dandavison/magit-delta/issues/13#issuecomment-949820122">Magit Delta Issue # 13&lt;/a> for more details.&lt;/dd>
&lt;/dl>
&lt;p>Now, I am alright with not seeing the line numbers in Magit. But I
really liked to see the line numbers in the side-by-side view in the
terminal. Luckily, if disabled the &lt;code>line-numbers&lt;/code> feature but enabled
the &lt;code>side-by-side&lt;/code> view, I got what I wanted!&lt;/p>
&lt;ol>
&lt;li>Line numbers are disabled in Magit and expanding/collapsing of
diffs works correctly. &lt;em>I am also really glad that I don&amp;rsquo;t see the
side-by-side view in Magit diffs even when I enable that feature in
&lt;code>delta&lt;/code>, because I like to have my Emacs buffers only about 90
characters wide.&lt;/em>&lt;/li>
&lt;li>Line numbers &lt;strong>and&lt;/strong> side-by-side view are enabled in the terminal.&lt;/li>
&lt;/ol>
&lt;p>I&amp;rsquo;ll end this post with pointers to installing &lt;code>delta&lt;/code> and
&lt;code>magit-delta&lt;/code> and how to configure them.&lt;/p>
&lt;h2 id="installing-delta">Installing &lt;code>delta&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#installing-delta">#&lt;/a>&lt;/h2>
&lt;p>You can install &lt;code>delta&lt;/code> (it&amp;rsquo;s called &lt;code>git-delta&lt;/code> in some package
managers) using one of the methods listed &lt;a href="https://dandavison.github.io/delta/installation.html">in its manual&lt;/a>, or you can
download → extract its statically compiled binary for your OS from its
&lt;a href="https://github.com/dandavison/delta/releases">GitHub Releases&lt;/a> page.&lt;/p>
&lt;h2 id="installing-magit-delta">Installing &lt;code>magit-delta&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#installing-magit-delta">#&lt;/a>&lt;/h2>
&lt;p>Once you put this snippet in your Emacs config and evaluate it, it
will install this package and enable the &lt;code>magit-delta-mode&lt;/code> in the
Magit buffers.&lt;/p>
&lt;p>&lt;a id="code-snippet--enabling-magit-delta">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">use-package&lt;/span> &lt;span class="nv">magit-delta&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">:ensure&lt;/span> &lt;span class="no">t&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">:hook&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-mode&lt;/span> &lt;span class="o">.&lt;/span> &lt;span class="nv">magit-delta-mode&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--enabling-magit-delta">Code Snippet 1&lt;/a>:&lt;/span>
Installing and enabling &lt;code>magit-delta&lt;/code> using &lt;code>use-package&lt;/code>
&lt;/div>
&lt;h2 id="configuring-delta">Configuring &lt;code>delta&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#configuring-delta">#&lt;/a>&lt;/h2>
&lt;p>Here&amp;rsquo;s a snippet for &lt;code>delta&lt;/code> configuration from my &lt;code>.gitconfig&lt;/code>. It&amp;rsquo;s
mostly the same as the one in &lt;em>delta&lt;/em>&amp;rsquo;s the &lt;a href="https://github.com/dandavison/delta#get-started">Getting Started&lt;/a> guide. The
main difference in my workaround for the &lt;code>magit-delta&lt;/code> issue.&lt;/p>
&lt;p>&lt;a id="code-snippet--delta-gitconfig">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-sh" data-lang="sh">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>core&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">pager&lt;/span> &lt;span class="o">=&lt;/span> delta
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>interactive&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">diffFilter&lt;/span> &lt;span class="o">=&lt;/span> delta --color-only
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>add.interactive&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">useBuiltin&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">false&lt;/span> &lt;span class="c1"># required for git 2.37.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>diff&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">colorMoved&lt;/span> &lt;span class="o">=&lt;/span> default
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>delta&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># https://github.com/dandavison/magit-delta/issues/13&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># line-numbers = true # Don&amp;#39;t do this.. messes up diffs in magit&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">#&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> side-by-side &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span> &lt;span class="c1"># Display a side-by-side diff view instead of the traditional view&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># navigate = true # Activate diff navigation: use n to jump forwards and N to jump backwards&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> relative-paths &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span> &lt;span class="c1"># Output all file paths relative to the current directory&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> file-style &lt;span class="o">=&lt;/span> yellow
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> hunk-header-style &lt;span class="o">=&lt;/span> line-number syntax
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--delta-gitconfig">Code Snippet 2&lt;/a>:&lt;/span>
My configuration for &lt;code>delta&lt;/code> in &lt;code>.gitconfig&lt;/code>
&lt;/div></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/tags/git">git</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><category domain="https://scripter.co/tags/magit">magit</category><category domain="https://scripter.co/tags/diff">diff</category><guid>https://scripter.co/using-git-delta-with-magit/</guid><pubDate>Wed, 06 Jul 2022 22:04:00 -0400</pubDate></item><item><title>View GitHub Pull Requests in Magit</title><link>https://scripter.co/view-github-pull-requests-in-magit/</link><description>&lt;blockquote>How to view GitHub Pull Request branches locally in the cloned repo,
and more importantly, how to do that automatically from within Emacs.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#locally-creating-a-branch-for-a-pr">Locally creating a branch for a PR&lt;/a>&lt;/li>
&lt;li>&lt;a href="#getting-references-to-all-pull-requests">Getting references to all Pull Requests&lt;/a>&lt;/li>
&lt;li>&lt;a href="#automatically-adding-pr-refs">Automatically adding PR refs&lt;/a>&lt;/li>
&lt;li>&lt;a href="#summary">Summary&lt;/a>&lt;/li>
&lt;li>&lt;a href="#references">References&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>I have a few public projects in git repos, but I don&amp;rsquo;t get that much
traffic in &lt;em>Pull Requests (PR)&lt;/em>
&lt;span class="sidenote-number">&lt;small class="sidenote">
Gitlab calls these &lt;em>Merge Requests&lt;/em> or MRs.
&lt;/small>&lt;/span>
. So when I need to add additional commits to a PR, I would just add
the PR author&amp;rsquo;s &lt;em>remote&lt;/em> to my local repo, &lt;em>check out&lt;/em> their PR
branch, add my own commits and then merge that to my project&amp;rsquo;s &lt;em>main&lt;/em>
branch.&lt;/p>
&lt;p>As these occurrences were few and far apart, I didn&amp;rsquo;t have a need to
view the &lt;em>PR branches&lt;/em> directly from within Emacs/Magit. Though, I
somehow knew that each GitHub Pull Request&amp;rsquo;s &lt;em>HEAD&lt;/em> got assigned a &lt;a href="https://git-scm.com/book/en/v2/Git-Internals-Git-References">git
&lt;strong>reference&lt;/strong>&lt;/a>. But I didn&amp;rsquo;t need to use that knowledge until today
😃.&lt;/p>
&lt;p>Today, when discussing &lt;a href="https://github.com/protesilaos/denote/pull/20">PR # 20&lt;/a> on &lt;a href="https://protesilaos.com/">Prot&amp;rsquo;s&lt;/a> &lt;a href="https://protesilaos.com/emacs/denote">Denote&lt;/a> package&amp;rsquo;s GitHub
mirror
&lt;span class="sidenote-number">&lt;small class="sidenote">
Prot uses &lt;a href="https://git.sr.ht/~protesilaos/denote">SourceHut&lt;/a> as the primary git forge for his Emacs
packages. But I am glad that he doesn&amp;rsquo;t mind the activity in Issues
and Pull Requests on the GitHub mirror.
&lt;/small>&lt;/span>
, he wrote &lt;a href="https://github.com/protesilaos/denote/pull/20#issuecomment-1164676013">this comment&lt;/a>:&lt;/p>
&lt;blockquote>
&lt;p>Now I just need to figure out how best to incorporate your changes
into the &lt;code>org-id&lt;/code> branch so I can add the final bits. I am not too
familiar with the PR workflow &amp;hellip;&lt;/p>
&lt;/blockquote>
&lt;p>.. and that inspired this post today.&lt;/p>
&lt;h2 id="locally-creating-a-branch-for-a-pr">Locally creating a branch for a PR&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#locally-creating-a-branch-for-a-pr">#&lt;/a>&lt;/h2>
&lt;p>From the &lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally">GitHub docs&lt;/a>, the &lt;code>git&lt;/code> command to create a local branch for a
PR is this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git fetch origin pull/ID/head:BRANCHNAME
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I have the &lt;code>denote&lt;/code> package cloned from its GitHub mirror. So the
&lt;strong>origin&lt;/strong> remote&amp;rsquo;s &lt;strong>url&lt;/strong> is &lt;code>https://github.com/protesilaos/denote&lt;/code>.&lt;/p>
&lt;div class="note">
&lt;p>Make sure that the remote name used in this command is pointing to a
GitHub repo, and not a mirror forge like GitLab or SourceHut.&lt;/p>
&lt;/div>
&lt;p>When I ran the below command, I got a new branch &lt;strong>pr-20&lt;/strong> pointing to
the latest commit of that PR:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">git fetch origin pull/20/head:pr-20
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Awesome!&lt;/p>
&lt;div class="verse">
&lt;p>.. But that wasn&amp;rsquo;t good enough&lt;br />
    .. Now I wanted more&lt;br />
        .. I didn&amp;rsquo;t want to manually create a branch for each PR.&lt;br />&lt;/p>
&lt;/div>
&lt;h2 id="getting-references-to-all-pull-requests">Getting references to all Pull Requests&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#getting-references-to-all-pull-requests">#&lt;/a>&lt;/h2>
&lt;p>Now that I was on that quest of &amp;ldquo;I want more&amp;rdquo;, it didn&amp;rsquo;t take me long
to re-discover &lt;a href="https://oremacs.com/2015/03/11/git-tricks/#illusion-2-quickly-get-github-pull-requests-on-your-system">this 7-year old nugget&lt;/a> by &lt;a href="https://oremacs.com">Oleh Krehel&lt;/a>. Here are the
relevant bits from that post:&lt;/p>
&lt;ol>
&lt;li>Open the local repo&amp;rsquo;s &lt;code>.git/config&lt;/code> file.&lt;/li>
&lt;li>Find the &lt;code>[remote &amp;quot;origin&amp;quot;]&lt;/code> section&lt;/li>
&lt;li>Modify it by adding this one line with &lt;strong>pull&lt;/strong> refs. &lt;em>This is the
same for all GitHub repositories.&lt;/em>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cfg" data-lang="cfg">&lt;span class="line">&lt;span class="cl">&lt;span class="k">[remote &amp;#34;origin&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">https://github.com/USER/REPO.git
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> fetch = +refs/heads/*:refs/remotes/origin/*
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line hl">&lt;span class="cl">&lt;span class="s"> fetch = +refs/pull/*/head:refs/pull/origin/*&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ol>
&lt;p>With that edit in place, when I did &lt;kbd>l&lt;/kbd> &lt;kbd>a&lt;/kbd> (show
the log for all git references), followed by &lt;kbd>f&lt;/kbd> &lt;kbd>a&lt;/kbd>
(fetch all the remotes) in the Magit, I could see the references to
the &lt;code>denote&lt;/code> repo&amp;rsquo;s PRs!&lt;/p>
&lt;p>&lt;a id="figure--magit-denote-pr-refs">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/view-github-pull-requests-in-magit/pr-20-ref.png" alt="Figure 1: Viewing PR references from denote package&amp;rsquo;s GitHub repo"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>Viewing PR references from &lt;code>denote&lt;/code> package&amp;rsquo;s GitHub repo
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;div class="verse">
&lt;p>.. But that still wasn&amp;rsquo;t good enough&lt;br />
    .. I didn&amp;rsquo;t want to manually edit the &lt;code>.git/config&lt;/code> in each repo.&lt;br />&lt;/p>
&lt;/div>
&lt;h2 id="automatically-adding-pr-refs">Automatically adding PR refs&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#automatically-adding-pr-refs">#&lt;/a>&lt;/h2>
&lt;p>Of course, I wasn&amp;rsquo;t the first one to think of this!&lt;/p>
&lt;p>Another Emacs veteran &lt;a href="https://endlessparentheses.com/">Artur Malabarba&lt;/a> had already had this covered
also around &lt;a href="https://endlessparentheses.com/automatically-configure-magit-to-access-github-prs.html">7 years back&lt;/a>. Coincidentally, that post was written as a
response to that same blog post by Oleh where he shared the above
&lt;code>.git/config&lt;/code> tip.&lt;/p>
&lt;p>In that post, Artur shares an Emacs Lisp function that uses Magit
functions like &lt;code>magit-get&lt;/code>, &lt;code>magit-get-all&lt;/code> and &lt;code>magit-git-string&lt;/code> to
auto-add the &lt;code>fetch = +refs/pull/*/head:refs/pull/origin/*&lt;/code> line in
the &lt;code>.git/config&lt;/code>. This magic happens after checking that the &lt;strong>origin&lt;/strong>
remote points to a GitHub repo, and if that line doesn&amp;rsquo;t already
exist.&lt;/p>
&lt;p>Here, I am lightly modifying the function shared in that post so that
the &lt;strong>origin&lt;/strong> remote name is not hard-coded
&lt;span class="sidenote-number">&lt;small class="sidenote">
The reason is that sometimes, I name the original remote as &lt;strong>upstream&lt;/strong>
and my fork as &lt;strong>fork&lt;/strong>, and I might have no remote named &lt;strong>origin&lt;/strong>.
&lt;/small>&lt;/span>
. Credit for the main logic in this code still goes to Artur.&lt;/p>
&lt;p>&lt;a id="code-snippet--add-PR-fetch-ref">&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">modi/add-PR-fetch-ref&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kp">&amp;amp;optional&lt;/span> &lt;span class="nv">remote-name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;If refs/pull is not defined on a GH repo, define it.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">If REMOTE-NAME is not specified, it defaults to the &lt;/span>&lt;span class="ss">`remote&amp;#39;&lt;/span>&lt;span class="s"> set
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">for the \&amp;#34;main\&amp;#34; or \&amp;#34;master\&amp;#34; branch.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let*&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">remote-name&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">or&lt;/span> &lt;span class="nv">remote-name&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get&lt;/span> &lt;span class="s">&amp;#34;branch&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;main&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get&lt;/span> &lt;span class="s">&amp;#34;branch&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;master&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">remote-url&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span> &lt;span class="s">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">fetch-refs&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">and&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">stringp&lt;/span> &lt;span class="nv">remote-url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">string-match&lt;/span> &lt;span class="s">&amp;#34;github&amp;#34;&lt;/span> &lt;span class="nv">remote-url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-get-all&lt;/span> &lt;span class="s">&amp;#34;remote&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span> &lt;span class="s">&amp;#34;fetch&amp;#34;&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; https://oremacs.com/2015/03/11/git-tricks/&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">fetch-address&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;+refs/pull/*/head:refs/pull/%s/*&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">when&lt;/span> &lt;span class="nv">fetch-refs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">unless&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">member&lt;/span> &lt;span class="nv">fetch-address&lt;/span> &lt;span class="nv">fetch-refs&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">magit-git-string&lt;/span> &lt;span class="s">&amp;#34;config&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;--add&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">format&lt;/span> &lt;span class="s">&amp;#34;remote.%s.fetch&amp;#34;&lt;/span> &lt;span class="nv">remote-name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">fetch-address&lt;/span>&lt;span class="p">)))))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nv">add-hook&lt;/span> &lt;span class="ss">&amp;#39;magit-mode-hook&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">modi/add-PR-fetch-ref&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="src-block-caption">
&lt;span class="src-block-number">&lt;a href="#code-snippet--add-PR-fetch-ref">Code Snippet 1&lt;/a>:&lt;/span>
Function to auto-add GitHub PR references to the repo's &lt;code>.git/config&lt;/code>
&lt;/div>
&lt;h2 id="summary">Summary&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#summary">#&lt;/a>&lt;/h2>
&lt;p>With the above snippet added to your Emacs config and evaluated, each
time you visit a repo cloned from GitHub in the Magit Status buffer
(&lt;code>M-x magit-status&lt;/code>), the PR refs will get auto-added to that repo&amp;rsquo;s
&lt;code>.git/config&lt;/code> if needed.&lt;/p>
&lt;p>After that, you can easily view the commits from all the PRs by doing
&lt;kbd>l&lt;/kbd> &lt;kbd>a&lt;/kbd> &lt;kbd>f&lt;/kbd> &lt;kbd>a&lt;/kbd>.&lt;/p>
&lt;h2 id="references">References&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#references">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://oremacs.com/2015/03/11/git-tricks/#illusion-2-quickly-get-github-pull-requests-on-your-system">oremacs &amp;ndash; Some git/magit/github tricks&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://endlessparentheses.com/automatically-configure-magit-to-access-github-prs.html">endlessparentheses &amp;ndash; Automatically configure Magit to access Github PRs&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally">GitHub &amp;ndash; Checking out PR branches locally&lt;/a>&lt;/li>
&lt;/ul></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/elisp">elisp</category><category domain="https://scripter.co/tags/git">git</category><category domain="https://scripter.co/tags/magit">magit</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><category domain="https://scripter.co/tags/github">github</category><category domain="https://scripter.co/tags/git-reference">git-reference</category><guid>https://scripter.co/view-github-pull-requests-in-magit/</guid><pubDate>Thu, 23 Jun 2022 17:51:00 -0400</pubDate></item><item><title>Creating a patch file using Magit</title><link>https://scripter.co/creating-a-patch-file-using-magit/</link><description>&lt;blockquote>Quick tip on how to create &lt;em>git&lt;/em> patch files in Emacs using Magit.&lt;/blockquote>&lt;div class="ox-hugo-toc toc">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;a href="#single-file-patch">Single-file patch&lt;/a>&lt;/li>
&lt;li>&lt;a href="#multi-file-patch">Multi-file patch&lt;/a>&lt;/li>
&lt;li>&lt;a href="#more-resources">More Resources&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>Recently I came across few instances where people were asking
questions related to creating patches for contributions to Emacs and
Org mode repos &lt;a href="https://www.reddit.com/r/emacs/comments/udjk8l/how_do_you_actually_send_pull_requests_in/">here&lt;/a> and then &lt;a href="https://github.com/kaushalmodi/ox-hugo/discussions/618#discussioncomment-2690410">here&lt;/a>. I was in the same shoes back then
when I was about to make my first contribution to Emacs. And so I
thought of sharing this tip on how to use Magit to create patch files.&lt;/p>
&lt;p>If you have been using both Emacs and git, you might have already
heard about the awesome &lt;a href="https://magit.vc/">Magit&lt;/a> package. If you haven&amp;rsquo;t 😲,
check out &lt;a href="https://emacsair.me/2017/09/01/magit-walk-through/">this screenshot-annotated review of what Magit is&lt;/a>. With that
out of the way, and assuming that you already have it installed
&lt;span class="sidenote-number">&lt;small class="sidenote">
&lt;code class="code-inline language-emacs-lisp">&lt;span class="p">(&lt;/span>&lt;span class="nb">use-package&lt;/span> &lt;span class="nv">magit&lt;/span> &lt;span class="nb">:ensure&lt;/span> &lt;span class="no">t&lt;/span>&lt;span class="p">)&lt;/span>&lt;/code>
&lt;/small>&lt;/span>
, here&amp;rsquo;s how to create a patch file using Magit ..&lt;/p>
&lt;h2 id="single-file-patch">Single-file patch&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#single-file-patch">#&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>Commit your changes to the git repo first.&lt;/li>
&lt;li>Bring up the &lt;strong>Magit Log&lt;/strong> view. From the Magit status buffer, you
would type &lt;kbd>l&lt;/kbd> &lt;kbd>l&lt;/kbd> to show the log of the current branch.&lt;/li>
&lt;li>Move the point to the commit that you want to send as a patch file,
and hit &lt;kbd>W&lt;/kbd> &lt;kbd>c&lt;/kbd> &lt;kbd>c&lt;/kbd> &lt;kbd>RET&lt;/kbd>.
&lt;ul>
&lt;li>The last &lt;kbd>RET&lt;/kbd> selects the commit the point is on, in the
∗magit-log∗ buffer.&lt;/li>
&lt;li>If the first line of the commit log of the selected commit is
&amp;ldquo;Update docstrings for shortdoc.el&amp;rdquo;, you&amp;rsquo;ll see a patch file
named &lt;code>0001-Update-docstrings-for-shortdoc.el.patch&lt;/code> created in
your git repo root.&lt;/li>
&lt;li>You can now email this patch file
&lt;mark>as an attachment&lt;/mark> to &lt;a href="mailto:bug-gnu-emacs@gnu.org">bug-gnu-emacs@gnu.org&lt;/a> (if contributing to Emacs) or to
&lt;a href="mailto:emacs-orgmode@gnu.org">emacs-orgmode@gnu.org&lt;/a> (if contributing to Org mode).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="multi-file-patch">Multi-file patch&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#multi-file-patch">#&lt;/a>&lt;/h2>
&lt;p>If you need to create a multi-file patch i.e. patch files for a series
of commits, select those commits in the ∗magit-log∗ buffer
&lt;span class="sidenote-number">&lt;small class="sidenote">
The commit selection process is the same as how you would select
text in any Emacs buffer. For example, if I want to create a series
of 5 patches, I would go to the latest commit in the series, hit
&lt;kbd>C-SPC&lt;/kbd> and then &lt;kbd>C-n&lt;/kbd> 4 times to select 5 rows of commits.
&lt;/small>&lt;/span>
, and then use the same &lt;kbd>W&lt;/kbd> &lt;kbd>c&lt;/kbd> &lt;kbd>c&lt;/kbd> binding.&lt;/p>
&lt;h2 id="more-resources">More Resources&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#more-resources">#&lt;/a>&lt;/h2>
&lt;p>Here are the official contribution guides for Emacs and Org mode:&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://git.savannah.gnu.org/cgit/emacs.git/tree/CONTRIBUTE">How to contribute to Emacs &amp;ndash; Emacs CONTRIBUTE document&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://orgmode.org/worg/org-contribute.html">How to contribute to Org &amp;ndash; Worg&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>Here are some more resources that got shared in the &lt;em>Emacsverse&lt;/em>
recently (within the past year as of writing this):&lt;/p>
&lt;ol>
&lt;li>&lt;span class="timestamp-wrapper">&lt;span class="timestamp">&amp;lt;2022-04-23 Sat&amp;gt; &lt;/span>&lt;/span> &lt;a href="https://lists.gnu.org/r/emacs-orgmode/2022-04/orgYGCOr0hBKH.org">Contributing patches to Org &amp;ndash; Ihor Radchenko&lt;/a>&lt;/li>
&lt;li>&lt;span class="timestamp-wrapper">&lt;span class="timestamp">&amp;lt;2022-04-09 Sat&amp;gt; &lt;/span>&lt;/span> &lt;a href="https://protesilaos.com/codelog/2022-04-09-simple-guide-git-patches-emacs/">Primer on formatting Git patches with Emacs (Magit) &amp;ndash; Protesilaos Stavrou&lt;/a>&lt;/li>
&lt;li>&lt;span class="timestamp-wrapper">&lt;span class="timestamp">&amp;lt;2021-08-17 Tue&amp;gt; &lt;/span>&lt;/span> &lt;a href="https://www.fosskers.ca/en/blog/contributing-to-emacs">Contributing to Emacs &amp;ndash; Colin Woodbury&lt;/a>&lt;/li>
&lt;/ol></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/tags/git">git</category><category domain="https://scripter.co/tags/magit">magit</category><category domain="https://scripter.co/tags/100daystooffload">100DaysToOffload</category><guid>https://scripter.co/creating-a-patch-file-using-magit/</guid><pubDate>Sun, 08 May 2022 08:48:00 -0400</pubDate></item><item><title>Git diff Minified JS and CSS</title><link>https://scripter.co/git-diff-minified-js-and-css/</link><description>&lt;blockquote>Make the &lt;code>git diff&lt;/code> output be more useful when diffing minified &lt;em>.js&lt;/em>
and &lt;em>.css&lt;/em> files.&lt;/blockquote>&lt;div class="ox-hugo-toc toc has-section-numbers">
&lt;div class="heading">Table of Contents&lt;/div>
&lt;ul>
&lt;li>&lt;span class="section-num">1&lt;/span> &lt;a href="#install-js-beautify-using-npm">Install &lt;code>js-beautify&lt;/code> using &lt;code>npm&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;span class="section-num">2&lt;/span> &lt;a href="#configure-git-to-use-that-tool">Configure &lt;code>git&lt;/code> to use that tool&lt;/a>&lt;/li>
&lt;li>&lt;span class="section-num">3&lt;/span> &lt;a href="#add-update-dot-gitattributes-file-to-the-project-repo">Add/update &lt;code>.gitattributes&lt;/code> file to the project repo&lt;/a>&lt;/li>
&lt;li>&lt;a href="#beautiful-result">Beautiful Result&lt;/a>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;!--endtoc-->
&lt;p>While working on a &lt;a href="https://github.com/gohugoio/gohugoioTheme/pull/84">little PR for the Hugo doc site theme&lt;/a>, I learned
that if I needed to make changes to JS/CSS, I had to commit my changes
in both unminified and minified versions.&lt;/p>
&lt;p>I have a habit to always look at the diffs at the time of staging and
committing. So it felt very unnatural to commit a minified JS where
the diff would show just &lt;strong>one&lt;/strong> changed line with thousands of
characters of minified+uglified JS.&lt;/p>
&lt;p>So I started looking for solutions, and found &lt;a href="https://cweiske.de/tagebuch/git-diff-minified-js.htm">this post&lt;/a> by &lt;em>Christian
Weiske&lt;/em> where he suggests using &lt;a href="https://github.com/beautify-web/js-beautify">&lt;code>js-beautify&lt;/code>&lt;/a> to &lt;em>beautify&lt;/em> minified
JS diffs.&lt;/p>
&lt;div class="verse">
&lt;p>    &lt;em>And that tool works beautifully!&lt;/em>&lt;br />&lt;/p>
&lt;/div>
&lt;ul>
&lt;li>I later found out that the same tool can also be used to &lt;em>beautify&lt;/em>
minified CSS.&lt;/li>
&lt;li>.. and I installed that tool using &lt;code>npm&lt;/code> as the &lt;code>pip3&lt;/code> approach
failed with &lt;em>&amp;ldquo;Collecting js-beautify.. Could not find a version that
satisfies the requirement js-beautify (from versions: ) No matching
distribution found for js-beautify&amp;rdquo;&lt;/em>.&lt;/li>
&lt;/ul>
&lt;p>So here&amp;rsquo;s how you can do useful &lt;code>git diff&lt;/code> for minified JS and CSS.&lt;/p>
&lt;h2 id="install-js-beautify-using-npm">&lt;span class="section-num">1&lt;/span> Install &lt;code>js-beautify&lt;/code> using &lt;code>npm&lt;/code>&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#install-js-beautify-using-npm">#&lt;/a>&lt;/h2>
&lt;p>I see myself using &lt;code>js-beautify&lt;/code> in many other projects too. So I
installed it globally.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">npm install --global js-beautify
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;h2 id="configure-git-to-use-that-tool">&lt;span class="section-num">2&lt;/span> Configure &lt;code>git&lt;/code> to use that tool&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#configure-git-to-use-that-tool">#&lt;/a>&lt;/h2>
&lt;p>Add below to your &lt;code>~/.gitconfig&lt;/code>:&lt;/p>
&lt;ol>
&lt;li>Use &lt;code>js-beautify&lt;/code> to first beautify the minified JS for the &lt;code>minjs&lt;/code>
&lt;em>diff configuration&lt;/em>, and then do a diff of those beautified files.&lt;/li>
&lt;li>Enable caching of those beautified files to speed up the diff, so
that &lt;em>re-beautification&lt;/em> of unmodified minified files can be
skipped.&lt;/li>
&lt;li>Similarly for minified CSS, use &lt;code>js-beautify --css&lt;/code> to first
beautify the minified CSS for the &lt;code>mincss&lt;/code> &lt;em>diff configuration&lt;/em>.&lt;/li>
&lt;/ol>
&lt;!--listend-->
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="k">[diff &amp;#34;minjs&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">textconv&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">js-beautify
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> cachetextconv = true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">[diff &amp;#34;mincss&amp;#34;]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">textconv&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">js-beautify --css
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s"> cachetextconv = true&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;h2 id="add-update-dot-gitattributes-file-to-the-project-repo">&lt;span class="section-num">3&lt;/span> Add/update &lt;code>.gitattributes&lt;/code> file to the project repo&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#add-update-dot-gitattributes-file-to-the-project-repo">#&lt;/a>&lt;/h2>
&lt;p>Now, in your project repo&amp;rsquo;s &lt;code>.gitattributes&lt;/code> file, you need to
associate files with the &lt;em>diff configurations&lt;/em> set above.&lt;/p>
&lt;p>Below will use the &lt;code>minjs&lt;/code> configuration for &lt;em>*.min.js&lt;/em> and
&lt;em>*.bundle.js&lt;/em> files, and &lt;code>mincss&lt;/code> configuration for &lt;em>*.min.css&lt;/em> and
&lt;em>main.css&lt;/em>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-ini" data-lang="ini">&lt;span class="line">&lt;span class="cl">&lt;span class="na">*.min.js diff&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">minjs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">*.bundle.js diff&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">minjs&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">*.min.css diff&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">mincss&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="na">main.css diff&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">mincss&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>
&lt;h2 id="beautiful-result">Beautiful Result&amp;nbsp;&lt;a class="headline-hash no-text-decoration" href="#beautiful-result">#&lt;/a>&lt;/h2>
&lt;p>&lt;a id="figure--git-diff-min-js">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/git-diff-minified-js-and-css/git-diff-minified-js.png" alt="Figure 1: git diff of minified JS as seen in Magit"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>&lt;code>git diff&lt;/code> of minified JS as seen in &lt;em>Magit&lt;/em>
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;p>Isn&amp;rsquo;t that better than how GitHub shows the &lt;em>exact same commit
diff&lt;/em>? 😎&lt;/p>
&lt;p>&lt;a id="figure--github-diff-min-js">&lt;/a>&lt;/p>
&lt;figure>
&lt;img src="https://scripter.co/git-diff-minified-js-and-css/github-diff-minified-js.png" alt="Figure 2: Same commit diff shown on GitHub"/> &lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 2: &lt;/span>Same commit &lt;code>diff&lt;/code> shown on &lt;em>GitHub&lt;/em>
&lt;/p>
&lt;/figcaption>&lt;/figure></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/web">web</category><category domain="https://scripter.co/categories/unix">unix</category><category domain="https://scripter.co/tags/minified">minified</category><category domain="https://scripter.co/tags/javascript">javascript</category><category domain="https://scripter.co/tags/git">git</category><category domain="https://scripter.co/tags/diff">diff</category><category domain="https://scripter.co/tags/css">css</category><category domain="https://scripter.co/tags/magit">magit</category><guid>https://scripter.co/git-diff-minified-js-and-css/</guid><pubDate>Mon, 19 Mar 2018 18:13:00 -0400</pubDate></item><item><title>Narrowing the Author column in Magit</title><link>https://scripter.co/narrowing-the-author-column-in-magit/</link><description>&lt;p>The Org and &lt;a href="https://orgmode.org/worg/">Worg&lt;/a> git repos can be committed to only via &lt;em>ssh&lt;/em> protocol
(and not &lt;em>https&lt;/em>), and for technical reasons, I cannot commit to those
repos via &lt;em>ssh&lt;/em> from my primary development machine. So I ended up
with a flow that involves pushing commits to those repos using my
Nexus 6p phone.&lt;/p>
&lt;p>&lt;a href="https://magit.vc/">Magit&lt;/a> is how I &lt;em>git&lt;/em>, and I love to primarily work from the
&lt;em>∗magit-log∗&lt;/em> buffer (&lt;code>M-x magit-status&lt;/code>, &lt;kbd>l&lt;/kbd> &lt;kbd>b&lt;/kbd>). But the default
column widths were not optimal on a Nexus 6p 5.7&amp;quot; screen. And that&amp;rsquo;s
what inspired this tweak, which looks great on a regular desktop
monitor too.&lt;/p>
&lt;p>Before I jump to the code, you can see in the below figure how the
author and commit age columns took up roughly half the screen width on
my phone before the tweak (left), and how much easier it is to read
the commit messages after the tweak (right).&lt;/p>
&lt;figure>
&lt;a href="https://scripter.co/images/magit_author_column.png">
&lt;img src="https://scripter.co/images/magit_author_column.png" alt="Figure 1: Org-mode Worg commit log : Before (Left), After (Right)"/> &lt;/a>&lt;figcaption>
&lt;p>
&lt;span class="figure-number">Figure 1: &lt;/span>Org-mode Worg commit log : Before (Left), After (Right)
&lt;/p>
&lt;/figcaption>&lt;/figure>
&lt;p>So the Magit Log columns tweaks are basically:&lt;/p>
&lt;ol>
&lt;li>Abbreviate the authors&amp;rsquo; first names to just their initials.&lt;/li>
&lt;li>Abbreviate the commit ages to 1-character time units.&lt;/li>
&lt;/ol>
&lt;p>To implement those tweaks, I started digging through &lt;code>magit-log.el&lt;/code>
and found that I would need to customize (i) the &lt;code>magit-log-margin&lt;/code>
variable and (ii) &lt;code>magit-log-format-margin&lt;/code> function.&lt;/p>
&lt;ul>
&lt;li>Customizing &lt;code>magit-log-margin&lt;/code> variable allows me to use the
abbreviated age instead of the verbose age strings (minute→m,
hour→h, day→d, week→w, month→M, year→Y). It&amp;rsquo;s also where I specify
how wide I want the author column to be.. I can now reduce that
column width from the default value of 18 to 11 as I am abbreviating
the author name too.&lt;/li>
&lt;li>Reviewing the &lt;code>magit-log.el&lt;/code> code, I realized that I also need to
advise the &lt;code>magit-log-format-margin&lt;/code> function to implement the
author name abbreviation.&lt;/li>
&lt;/ul>
&lt;p>In the below code snippet, I am using &lt;a href="https://github.com/jwiegley/use-package">&lt;code>use-package&lt;/code>&lt;/a>&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup> to customize
that variable and function in &lt;code>magit-log&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">&lt;span class="line">&lt;span class="cl">&lt;span class="p">(&lt;/span>&lt;span class="nb">use-package&lt;/span> &lt;span class="nv">magit-log&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">:init&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">progn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; (setq magit-log-margin &amp;#39;(t age magit-log-margin-width t 18)) ;Default value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">setq&lt;/span> &lt;span class="nv">magit-log-margin&lt;/span> &lt;span class="o">&amp;#39;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">t&lt;/span> &lt;span class="nv">age-abbreviated&lt;/span> &lt;span class="nv">magit-log-margin-width&lt;/span> &lt;span class="nb">:author&lt;/span> &lt;span class="mi">11&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">:config&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">progn&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; Abbreviate author name. I added this so that I can view Magit log without&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; too much commit message truncation even on narrow screens (like on phone).&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">defun&lt;/span> &lt;span class="nv">modi/magit-log--abbreviate-author&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kp">&amp;amp;rest&lt;/span> &lt;span class="nv">args&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">&amp;#34;The first arg is AUTHOR, abbreviate it.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">First Last -&amp;gt; F Last
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">First.Last -&amp;gt; F Last
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">Last, First -&amp;gt; F Last
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">First -&amp;gt; First (no change).
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s">It is assumed that the author has only one or two names.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; ARGS -&amp;gt; &amp;#39;((REV AUTHOR DATE))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; (car ARGS) -&amp;gt; &amp;#39;(REV AUTHOR DATE)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; (nth 1 (car ARGS)) -&amp;gt; AUTHOR&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">let*&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="nv">author&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">nth&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">car&lt;/span> &lt;span class="nv">args&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">author-abbr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">string-match-p&lt;/span> &lt;span class="s">&amp;#34;,&amp;#34;&lt;/span> &lt;span class="nv">author&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; Last, First -&amp;gt; F Last&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">replace-regexp-in-string&lt;/span> &lt;span class="s">&amp;#34;\\(.*?\\), *\\(.\\).*&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;\\2 \\1&amp;#34;&lt;/span> &lt;span class="nv">author&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">;; First Last -&amp;gt; F Last&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">replace-regexp-in-string&lt;/span> &lt;span class="s">&amp;#34;\\(.\\).*?[. ]+\\(.*\\)&amp;#34;&lt;/span> &lt;span class="s">&amp;#34;\\1 \\2&amp;#34;&lt;/span> &lt;span class="nv">author&lt;/span>&lt;span class="p">))))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">setf&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">nth&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nf">car&lt;/span> &lt;span class="nv">args&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="nv">author-abbr&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nf">car&lt;/span> &lt;span class="nv">args&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="c1">;&amp;#39;(REV AUTHOR-ABBR DATE)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nv">advice-add&lt;/span> &lt;span class="ss">&amp;#39;magit-log-format-margin&lt;/span> &lt;span class="nb">:filter-args&lt;/span> &lt;span class="nf">#&amp;#39;&lt;/span>&lt;span class="nv">modi/magit-log--abbreviate-author&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>NOTES&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>I need to set the &lt;code>magit-log-margin&lt;/code> value in the &lt;code>:init&lt;/code> block
because that variable dynamically sets many other variables in
&lt;code>magit-log&lt;/code> at the time of loading. So we cannot wait for the whole
&lt;code>magit-log&lt;/code> to load before setting that variable. I wouldn&amp;rsquo;t need to
worry about this if I were using the Emacs &lt;em>Customize&lt;/em> interface to
set this variable.&lt;/li>
&lt;li>I use &lt;code>modi/magit-log--abbreviate-author&lt;/code> to add a &lt;code>:filter-args&lt;/code>
advice to &lt;code>magit-log-format-margin&lt;/code>. The signature of the advised
function is &lt;code>(magit-log-format-margin REV AUTHOR DATE)&lt;/code> (as of
&lt;em>Magit 20180809.1716&lt;/em>). So the advice basically replaces the
&lt;code>AUTHOR&lt;/code> arg with its abbreviated form as explained in the
&lt;code>modi/magit-log--abbreviate-author&lt;/code> doc-string.&lt;/li>
&lt;/ul>
&lt;div class="footnotes" role="doc-endnotes">
&lt;hr>
&lt;ol>
&lt;li id="fn:1">
&lt;p>Feel free to ask for more explanation in comments in the case
you don&amp;rsquo;t use &lt;code>use-package&lt;/code>.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink">&amp;#x21a9;&amp;#xfe0e;&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;/div></description><author>Kaushal.Modi@fakeEmailToMakeValidatorHappy.com (Kaushal Modi)</author><category domain="https://scripter.co/categories/emacs">emacs</category><category domain="https://scripter.co/categories/elisp">elisp</category><category domain="https://scripter.co/tags/magit">magit</category><category domain="https://scripter.co/tags/git">git</category><category domain="https://scripter.co/tags/org">org</category><category domain="https://scripter.co/tags/log">log</category><guid>https://scripter.co/narrowing-the-author-column-in-magit/</guid><pubDate>Mon, 18 Dec 2017 16:36:00 -0500</pubDate></item></channel></rss>