{"id":1027,"date":"2019-12-12T21:04:11","date_gmt":"2019-12-12T20:04:11","guid":{"rendered":"https:\/\/blogs.gentoo.org\/mgorny\/?p=1027"},"modified":"2019-12-16T09:08:48","modified_gmt":"2019-12-16T08:08:48","slug":"a-better-ebuild-workflow-with-pure-git-and-pkgcheck","status":"publish","type":"post","link":"https:\/\/blogs.gentoo.org\/mgorny\/2019\/12\/12\/a-better-ebuild-workflow-with-pure-git-and-pkgcheck\/","title":{"rendered":"A\u00a0better ebuild workflow with pure git and\u00a0pkgcheck"},"content":{"rendered":"<p>Many developers today continue using <kbd>repoman commit<\/kbd> as&nbsp;their primary way of&nbsp;committing to&nbsp;Gentoo.  While this tool was quite helpful, if&nbsp;not&nbsp;indispensable in&nbsp;times of&nbsp;CVS, today it&#8217;s a&nbsp;burden.  The&nbsp;workflow using a&nbsp;single serial tool to&nbsp;check your packages and&nbsp;commit to&nbsp;them is not&nbsp;very efficient.  Not only it wastes your time and&nbsp;slows you down \u2014 it discourages you from splitting your changes into more atomic commits.<\/p>\n<p>Upon hearing the&nbsp;pkgcheck advocacy, many developers ask whether it can commit for you.  It won&#8217;t do that, that&#8217;s not its purpose.  Not only it&#8217;s waste of&nbsp;time to&nbsp;implement that \u2014 it would actually make it a&nbsp;worse tool.  With its parallel engine pkgcheck really shines when dealing with&nbsp;multiple packages \u2014 forcing it to&nbsp;work on&nbsp;one package is a&nbsp;waste of&nbsp;its potential.<\/p>\n<p>Rather than trying to&nbsp;proliferate your <em>bad<\/em> old habits, you should learn how to&nbsp;use git and&nbsp;pkgcheck efficiently.  This post aims to&nbsp;give you a&nbsp;few advices.<\/p>\n<p><!--more--><\/p>\n<h2>pkgcheck after committing<\/h2>\n<p>Repoman was built under the&nbsp;assumption that checks should be&nbsp;done prior to&nbsp;committing.  That is understandable when you&#8217;re working on&nbsp;a&nbsp;\u2018live\u2019 repository as&nbsp;the&nbsp;ones used by&nbsp;CVS or&nbsp;Subversion.  However, in&nbsp;case of&nbsp;VCS-es involving staging commits such as&nbsp;Git there is no&nbsp;real difference between checking prior to&nbsp;or&nbsp;post commit.  The&nbsp;most efficient pkgcheck workflow is to&nbsp;check once all changes are committed and&nbsp;you are ready to&nbsp;push.<\/p>\n<p>The&nbsp;most recent version of&nbsp;pkgcheck has a&nbsp;command just for that:<\/p>\n<pre><code>$ pkgcheck scan --commits<\/code><\/pre>\n<p>Yes, it&#8217;s that simple.  It checks what you&#8217;ve committed compared to&nbsp;<kbd>origin<\/kbd> (note: you&#8217;ll need to&nbsp;have a&nbsp;correct <kbd>origin<\/kbd> remote), and&nbsp;runs scan on&nbsp;all those packages.  Now, if&nbsp;you&#8217;re committing changes to&nbsp;multiple packages (which should be&nbsp;pretty common), the&nbsp;scan is run in&nbsp;parallel to&nbsp;utilize your CPU power better.<\/p>\n<p>You might say: but&nbsp;repoman ensures that my commit message is neat these days!  Guess what.  The&nbsp;<kbd>--commits<\/kbd> option does exactly that \u2014 it raises warnings if your commit message is bad.  Admittedly, it only checks summary line at&nbsp;the&nbsp;moment but that&#8217;s something that can (and&nbsp;will) be&nbsp;improved easily.<\/p>\n<p><ins>And\u00a0I&#8217;ve forgotten the\u00a0most cool thing of\u00a0all: pkgcheck also reports if\u00a0you accidentally remove the\u00a0newest ebuild with stable keywords on\u00a0given arch!<\/ins><\/p>\n<p>One more tip.  You can use the&nbsp;following option to&nbsp;include full live verification of&nbsp;URLs:<\/p>\n<pre><code>$ pkgcheck scan --net --commits<\/code><\/pre>\n<p>Again, this is a&nbsp;feature missing entirely from&nbsp;repoman.<\/p>\n<h2>pkgcommit to&nbsp;ease committing to&nbsp;ebuilds<\/h2>\n<p>While the&nbsp;majority of&nbsp;repoman&#8217;s VCS support is&nbsp;superficial or&nbsp;better implemented elsewhere, there&#8217;s one killer feature worth keeping: automatically prepending the&nbsp;package name to the&nbsp;summary line.  Since that is a&nbsp;really trivial thing, I&#8217;ve reimplemented it in&nbsp;a&nbsp;few lines of&nbsp;bash as&nbsp;<a rel=\"external\" href=\"https:\/\/github.com\/mgorny\/mgorny-dev-scripts\/blob\/master\/pkgcommit\">pkgcommit<\/a>.<\/p>\n<p>When run in&nbsp;a&nbsp;package directory, it runs an editor with pre-filled commit message template to&nbsp;let you type it in, then passes it along with its own arguments to git.  Usually, I use it as (I like to be&nbsp;explicit about signoffs and&nbsp;signing, you can make <kbd>.git\/config<\/kbd> take care of&nbsp;it):<\/p>\n<pre><code>$ pkgcommit -sS .<\/code><\/pre>\n<p>Its extra feature is that it processes <kbd>-m<\/kbd> option and&nbsp;lets you skip the&nbsp;editor for&nbsp;simple messages:<\/p>\n<pre><code>$ pkgcommit -sS . -m 'Bump to 1.2.3'<\/code><\/pre>\n<p>Note that it <em>does not<\/em> go out of&nbsp;its way to figure out what to&nbsp;commit.  You need to&nbsp;either stage changes yourself via&nbsp;<kbd>git add<\/kbd>, or&nbsp;pass appropriate paths to&nbsp;the&nbsp;command.  What&#8217;s important is that it does not&nbsp;limit you to&nbsp;committing to&nbsp;one directory \u2014 you can e.g. include some profile changes easily.<\/p>\n<p>You&#8217;ll also need <kbd>pkg<\/kbd> script from the&nbsp;same repository.  Or&nbsp;you just install the&nbsp;whole bundle of&nbsp;<kbd>app-portage\/mgorny-dev-scripts<\/kbd>.<\/p>\n<h2>Amending commits via&nbsp;fixups<\/h2>\n<p>Most of&nbsp;you know probably know that you can update commits via&nbsp;<kbd>git commit --amend<\/kbd>.  However, that&#8217;s useful only for&nbsp;editing the&nbsp;most recent commit.  You can also use interactive rebase to&nbsp;choose specific commits for&nbsp;editing, and&nbsp;then amend them.  Yet, usually there&#8217;s a&nbsp;much more convenient way of&nbsp;doing that.<\/p>\n<p>In&nbsp;order to&nbsp;commit a&nbsp;<em>fixup<\/em> to a&nbsp;particular past commit, use:<\/p>\n<pre><code>$ git commit --fixup OLD_COMMIT_ID<\/code><\/pre>\n<p>This will create a&nbsp;specially titled commit that will be automatically picked up and&nbsp;ordered by&nbsp;the&nbsp;interactive rebase:<\/p>\n<pre><code>$ git rebase -i -S origin<\/code><\/pre>\n<p>Again, I have a&nbsp;tool of&nbsp;greater convenience.  Frequently, I just want to update the&nbsp;latest commit to&nbsp;a&nbsp;particular package (directory).  <a rel=\"external\" href=\"https:\/\/github.com\/mgorny\/mgorny-dev-scripts\/blob\/master\/git-fixup\">git-fixup<\/a> does exactly that \u2014 it finds the&nbsp;identifier of&nbsp;the&nbsp;latest commit to a&nbsp;particular file\/directory (or&nbsp;the&nbsp;current directory when no&nbsp;parameter is&nbsp;given) and&nbsp;commits a&nbsp;fixup to that:<\/p>\n<pre><code>$ git-fixup .<\/code><\/pre>\n<p>Note that if&nbsp;you try to&nbsp;push fixups into the&nbsp;repository, <em>nothing will stop you<\/em>.  This is one of&nbsp;the&nbsp;reasons that I don&#8217;t enable signoffs and&nbsp;signing on&nbsp;all commits by&nbsp;default.  This way, if&nbsp;I&nbsp;forget to&nbsp;rebase my fixups, the&nbsp;git hook will reject them as&nbsp;lacking signoff and\/or&nbsp;signature.<\/p>\n<p>Again, it is part of&nbsp;<kbd>app-portage\/mgorny-dev-scripts<\/kbd>.<\/p>\n<h2>Interactive rebase to the&nbsp;rescue<\/h2>\n<p>When trivial tools are no&nbsp;longer sufficient, interactive rebase is probably one of&nbsp;the&nbsp;best tools for&nbsp;editing your commits.  Start by&nbsp;initiating it for&nbsp;all commits since the&nbsp;last push:<\/p>\n<pre><code>$ git rebase -i -S origin<\/code><\/pre>\n<p>It will bring your editor with a&nbsp;list of&nbsp;all commits.  Using this list, you can do a&nbsp;lot: reorder commits, <kbd>drop<\/kbd> them, <kbd>reword<\/kbd> their commit messages, use <kbd>squash<\/kbd> or&nbsp;<kbd>fixup<\/kbd> to&nbsp;merge them into other commits, and&nbsp;finally: <kbd>edit<\/kbd> them (open for&nbsp;amending).<\/p>\n<p>The&nbsp;interactive rebase is&nbsp;probably the&nbsp;most powerful porcelain git command.  I&#8217;ve personally found the&nbsp;immediate tips given by&nbsp;git good enough but&nbsp;I&nbsp;realize that many people find it hard nevertheless.  Since it&#8217;s not my goal here to&nbsp;provide detailed instructions on&nbsp;using git, I&#8217;m going to&nbsp;suggest looking online for&nbsp;tutorials and&nbsp;guides.  The&nbsp;<a rel=\"external\" href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Tools-Rewriting-History\">Rewriting History<\/a> section of&nbsp;the&nbsp;Git Book also has a&nbsp;few examples.<\/p>\n<h2>Before pushing: git log<\/h2>\n<p><kbd>git log<\/kbd> seems to be&nbsp;one of&nbsp;the&nbsp;most underappreciated pre-push tools.  However, it can be of&nbsp;great service to&nbsp;you.  When run prior to&nbsp;pushing, it can help you verify that what you&#8217;re pushing is&nbsp;actually what you&#8217;ve meant to&nbsp;push.<\/p>\n<pre><code>$ git log --stat<\/code><\/pre>\n<p>will list all staged commits along with a&nbsp;pretty summary of&nbsp;affected files.  This can help you notice that you&#8217;ve forgotten to&nbsp;<kbd>git add<\/kbd> a&nbsp;patch, or&nbsp;that you&#8217;ve accidentally committed some extraneous change, or that you&#8217;ve just mixed changes from two commits.<\/p>\n<p>Of course, you can go even further and&nbsp;take a&nbsp;look at&nbsp;the&nbsp;changes in&nbsp;patch form:<\/p>\n<pre><code>$ git log -p<\/code><\/pre>\n<p>While I&nbsp;realize this is nothing new or&nbsp;surprising to&nbsp;you, sometimes it&#8217;s worthwhile to&nbsp;reiterate the&nbsp;basics in&nbsp;a&nbsp;different context to&nbsp;make you realize something obvious.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Many developers today continue using repoman commit as&nbsp;their primary way of&nbsp;committing to&nbsp;Gentoo. While this tool was quite helpful, if&nbsp;not&nbsp;indispensable in&nbsp;times of&nbsp;CVS, today it&#8217;s a&nbsp;burden. The&nbsp;workflow using a&nbsp;single serial tool to&nbsp;check your packages and&nbsp;commit to&nbsp;them is not&nbsp;very efficient. Not only it wastes your time and&nbsp;slows you down \u2014 it discourages you from splitting your changes into &hellip; <a href=\"https:\/\/blogs.gentoo.org\/mgorny\/2019\/12\/12\/a-better-ebuild-workflow-with-pure-git-and-pkgcheck\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;A\u00a0better ebuild workflow with pure git and\u00a0pkgcheck&#8221;<\/span><\/a><\/p>\n","protected":false},"author":137,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[11],"tags":[13],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/1027"}],"collection":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/users\/137"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/comments?post=1027"}],"version-history":[{"count":15,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/1027\/revisions"}],"predecessor-version":[{"id":1042,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/1027\/revisions\/1042"}],"wp:attachment":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/media?parent=1027"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/categories?post=1027"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/tags?post=1027"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}