148 lines
8.8 KiB
Plaintext
148 lines
8.8 KiB
Plaintext
<p><a href="https://www.manueluberti.eu/emacs/2021/11/21/eglot-and-vc/">Some days ago</a> I
|
||
briefly wrote about my willingness to give Emacs built-in VC system a try for
|
||
real. For real means that it’s easy to praise the beauties of <code class="language-plaintext highlighter-rouge">vc-git</code> when
|
||
working on personal projects such as this blog, but is VC actually worth it on
|
||
bigger projects where different people commit and push regularly, rebasing is a
|
||
habit, and merge conflicts are unavoidable necessities?</p>
|
||
|
||
<p>A warning first. This article is not intended as a VC tutorial. It aims to be an
|
||
example of how <em>I</em> use it or, to phrase it better, how I <em>started</em> to use it. As
|
||
<a href="https://www.masteringemacs.org/">Mickey Petersen</a> suggests in the “Exploring
|
||
Emacs” section of his great <em>Mastering Emacs</em> book, if you want to know more
|
||
about VC there is plenty of information right within our favourite text editor.
|
||
Furthermore, Protesilaos Stavrou has a couple of nice videos on VC you might
|
||
want to check out: <a href="https://www.youtube.com/watch?v=SQ3Beqn2CEc">Introduction to
|
||
VC</a> and <a href="https://www.youtube.com/watch?v=0YlYX_UjH5Q">Workflow with VC for
|
||
Git</a>.</p>
|
||
|
||
<p>Now, let’s break down a common workflow of mine:</p>
|
||
|
||
<ul>
|
||
<li>A new ticket is assigned to me</li>
|
||
<li>I create a new branch for this ticket, starting from the <code class="language-plaintext highlighter-rouge">master</code> one</li>
|
||
<li>I code my thing</li>
|
||
<li>I commit and push my code</li>
|
||
<li>I file a new merge request ready to be reviewed</li>
|
||
<li>The review may require changes to my code</li>
|
||
<li>I may need to rebase my changes onto <code class="language-plaintext highlighter-rouge">master</code> because other developers have
|
||
merged their branches before me</li>
|
||
<li>Merge conflicts may arise and need to be fixed</li>
|
||
<li>I push my updated code ready to be reviewed again</li>
|
||
<li>If everything’s fine I merge my changes, otherwise back to my
|
||
edit/rebase/merge process until it’s properly done</li>
|
||
<li>Meanwhile, it may happen that I need to stash my changes and quickly fix a
|
||
higher priority bug</li>
|
||
</ul>
|
||
|
||
<p>This more or less happens on a daily basis, so the interaction with Git (the
|
||
only VCS I have used in the last ten years) must be smooth. On the other hand,
|
||
Git-wise the above workflow is not that complicated. For instance, I rarely
|
||
use features such as cherry-picking or bisecting.</p>
|
||
|
||
<p>On the surface, the main difference between Magit and VC is <code class="language-plaintext highlighter-rouge">transient</code>. Magit
|
||
transient menus make all the operations I described above<sup id="fnref:1"><a class="footnote" href="https://www.manueluberti.eu/feed#fn:1" rel="footnote">1</a></sup> a breeze. From
|
||
checking out a branch to interactive rebasing, Magit requires few key strokes to
|
||
accommodate my needs. The blatant truth is that Magit wraps everything I want
|
||
from Git and much more in a user interface that just works.</p>
|
||
|
||
<p>VC, however, is not tightly coupled to Git, so it does not cover all of its many
|
||
options. And yet I was able to manage my work projects with VC alternatives to
|
||
Magit commands.</p>
|
||
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Operation</th>
|
||
<th>VC</th>
|
||
<th>Magit</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>Project status</td>
|
||
<td><code class="language-plaintext highlighter-rouge">project-vc-dir</code> (<kbd>C-x p v</kbd>)</td>
|
||
<td><code class="language-plaintext highlighter-rouge">magit-status</code> (<kbd>C-x g</kbd>)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Pull</td>
|
||
<td><code class="language-plaintext highlighter-rouge">vc-update</code> (<kbd>F</kbd>, in my case)</td>
|
||
<td><code class="language-plaintext highlighter-rouge">magit-pull</code> (<kbd>F p</kbd>)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>New branch</td>
|
||
<td><code class="language-plaintext highlighter-rouge">vc-retrieve-tag</code> (<kbd>C-u B s</kbd>)</td>
|
||
<td><code class="language-plaintext highlighter-rouge">magit-branch</code> (<kbd>b c</kbd>)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Commit</td>
|
||
<td><code class="language-plaintext highlighter-rouge">vc-next-action</code> (<kbd>C-x v v</kbd>)</td>
|
||
<td><code class="language-plaintext highlighter-rouge">magit-commit</code> (<kbd>c c</kbd>)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Rebase</td>
|
||
<td><code class="language-plaintext highlighter-rouge">shell-command</code> (<kbd>M-!</kbd>) + <code class="language-plaintext highlighter-rouge">git rebase master</code></td>
|
||
<td><code class="language-plaintext highlighter-rouge">magit-rebase</code> (<kbd>r p</kbd>)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Push</td>
|
||
<td><code class="language-plaintext highlighter-rouge">vc-push</code> (<kbd>P</kbd> or <kbd>C-u P</kbd>)</td>
|
||
<td><code class="language-plaintext highlighter-rouge">magit-push</code> (<kbd>P p</kbd>)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Stash</td>
|
||
<td><code class="language-plaintext highlighter-rouge">mu-vc-git-stash</code> (<kbd>z</kbd>)</td>
|
||
<td><code class="language-plaintext highlighter-rouge">magit-stash</code> (<kbd>z</kbd>)</td>
|
||
</tr>
|
||
<tr>
|
||
<td>Log</td>
|
||
<td><code class="language-plaintext highlighter-rouge">vc-print-root-log</code> (<kbd>L</kbd>)</td>
|
||
<td><code class="language-plaintext highlighter-rouge">magit-log</code> (<kbd>l l</kbd>)</td>
|
||
</tr>
|
||
<tr>
|
||
<td> </td>
|
||
<td> </td>
|
||
<td> </td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<p>VC has its own <code class="language-plaintext highlighter-rouge">vc-git-stash</code>, <code class="language-plaintext highlighter-rouge">vc-git-stash-pop</code>, and <code class="language-plaintext highlighter-rouge">vc-git-stash-delete</code>
|
||
commands, but instead of calling them via <kbd>M-x</kbd> every time I devised
|
||
<code class="language-plaintext highlighter-rouge">mu-vc-git-stash</code> and bound it to <kbd>z</kbd> in <code class="language-plaintext highlighter-rouge">vc-dir-mode-map</code>:</p>
|
||
|
||
<div class="language-emacs-lisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">mu-vc-git-stash</span> <span class="p">(</span><span class="nv">pop-or-delete</span><span class="p">)</span>
|
||
<span class="s">"Create, pop, or delete Git stashes.
|
||
With no POP-OR-DELETE call `vc-git-stash'. With one prefix
|
||
argument call `vc-git-stash-pop'. With two prefix arguments call
|
||
`vc-git-stash-delete'."</span>
|
||
<span class="p">(</span><span class="nv">interactive</span> <span class="s">"P"</span> <span class="nv">vc-dir-mode</span><span class="p">)</span>
|
||
<span class="p">(</span><span class="nb">cond</span> <span class="p">((</span><span class="nb">=</span> <span class="p">(</span><span class="nv">prefix-numeric-value</span> <span class="nv">pop-or-delete</span><span class="p">)</span> <span class="mi">4</span><span class="p">)</span>
|
||
<span class="p">(</span><span class="nv">call-interactively</span> <span class="nf">#'</span><span class="nv">vc-git-stash-pop</span><span class="p">))</span>
|
||
<span class="p">((</span><span class="nb">=</span> <span class="p">(</span><span class="nv">prefix-numeric-value</span> <span class="nv">pop-or-delete</span><span class="p">)</span> <span class="mi">16</span><span class="p">)</span>
|
||
<span class="p">(</span><span class="nv">call-interactively</span> <span class="nf">#'</span><span class="nv">vc-git-stash-delete</span><span class="p">))</span>
|
||
<span class="p">(</span><span class="no">t</span> <span class="p">(</span><span class="nv">call-interactively</span> <span class="nf">#'</span><span class="nv">vc-git-stash</span><span class="p">))))</span>
|
||
</code></pre></div></div>
|
||
|
||
<p>As you can see, <kbd>C-u z</kbd> issues <code class="language-plaintext highlighter-rouge">vc-git-stash-pop</code> while <kbd>C-u C-u
|
||
z</kbd> runs <code class="language-plaintext highlighter-rouge">vc-git-stash-delete</code>.</p>
|
||
|
||
<p>One thing that Magit really shines at for me is interactive rebasing (<kbd>r
|
||
i</kbd>). I haven’t had the opportunity so far to check how I can handle this
|
||
with VC. I guess a combination of <code class="language-plaintext highlighter-rouge">shell-command</code> and something I have yet to
|
||
discover would do, probably.</p>
|
||
|
||
<p>Anyway, I’ll keep using VC in the next days and report back if I manage to adapt
|
||
more of my Git workflows to it. I suspect Magit will outshine the humbler Emacs
|
||
built-in eventually, but who knows. Reading on the <code class="language-plaintext highlighter-rouge">emacs-devel</code> mailing list
|
||
that some wild Emacs developers prefer VC to Magit seems to confirm that the
|
||
world is still full of surprises.</p>
|
||
|
||
<h3 id="notes">Notes</h3>
|
||
|
||
<div class="footnotes">
|
||
<ol>
|
||
<li id="fn:1">
|
||
<p>Well, only the ones related to Git of course. <a class="reversefootnote" href="https://www.manueluberti.eu/feed#fnref:1">↩</a></p>
|
||
</li>
|
||
</ol>
|
||
</div> |