Artemis | Blog | Portfolio | About & Contact

2020 / 09 / 21 - Software discoveries (raw)

More on git

A while ago, I wrote an article about barebones git hosting in which I showcased the built-in git templating feature as a side note.

The most common feedback I received from it was to try to introduce some more "less-known" git features, and this led me to write this article.


Here, I will outline a few nifty commands and modules that are, in my humble opinion, pretty worth checking out, even if you won't end up using them.

git-annex: Track files without versioning their content

For non-LFS git projects, there is a way to manage heavy files without pulling them into the git tree.

Instead, the git-annex command will keep track of files based on checksums, and allow most standard git operations without having to set up a LFS server, or to destroy your git tree.

It allows tracking, moving, locking, synchronizing, files, but can do much more!

For example, the git annex addurl command will download the mailhook-0.0.2-py3-none-any.whl file into the local tree.

A different example is the git annex importfeed, documented as "Imports the contents of podcast feeds into the annex.". This effectively allows you to download a RSS feed into your tree.

Note that git-annex-importfeed is made for podcasts, and has a wrapper around the youtube-dl tool if you wish to download youtube playlists too.

Yes, this command is pretty sidetracked.

git-bundle: Package a git repository, or part of it

So let's say you're in an internet outage, but you really need to give your changes and part of your repository to a friend of yours.

You cannot use usual means because of the internet outage, so you cannot use HTTP, SSH, or anything else like that.

Thankfully, the git-bundle command is made to automatically create an archive of a branch or more, basically put part of a repository.

To extract the branches from the archive, you simply use the standard clone command, using a local path instead of an URL.

$ git clone -b main ~/Downloads/mymain.bundle ./git/repository

This will grab the main branch from the bundle stored in the downloads folder, and insert it into the git repository at ./git/repository.

Note that it also allows you to verify said archives.

git-am: E-mail based git contribution workflow

Let's say you like to use e-mails to manage your git contributions, sharing patchsets and such through it.

You could do so by hand, downloading the patchsets and applying them with the git apply command, but git provides a few cool utilities to manage your e-mail based workflow.

One of said commands is git-am, tasked with pulling git contributions from your mailbox, and parse / apply them right away.

Additionally, it also allows to apply a patch / patchset file, using the simple command git am ~/Downloads/contributions.patch.

git-archive: Archiving the tree at a given commit into a bundle

If you want to grab the tree at a given commit, or head, but don't want to clone, duplicate, or checkout your currently used repository, you can easily extract everything you'd get if you checked out a reference, but instead of modifying your work tree, the git-archive command will put everything in a tarball archive for you to move around or unpack.

For example, let's say I wanna get the working tree from the first release of my project, so I can publish it.

$ git archive --format=tar.gz --prefix project v1.0.0 > project-1.0.0.tar.gz

Boom, now the unpacking will put everything from the version tagged by v1.0.0 in a folder named project.

But what if you just wanna check out the main branch from your project, to compare it with your currently checked out feature branch?

You don't have to manually pack / unpack, thanks to the unix command chaining magic.

$ git archive --format=tar --prefix main project-main | (cd .. && tar xf -)

Now the project's main branch will be available in the project-main folder, alongside your project's feature folder.


Here, I will outline some concepts and features provided by git.

The only difference between this section and the previous one is the fact that concepts here are mostly configuration-bound or environment-bound, and not based on git commands.

Git namespaces

What if you want to avoid replicating the same codebase 10 times, but submodules and libraries are too bothersome for your context?

Well, git provides a way to group and separate your references by namespaces.

The concept of git namespacing is to have a common repository (on which you will have everything, and on which you can run a single common git gc command, besides other maintenance operations), but which you can split into different names.

A name is a group of branches, tags, and other kinds of references, which you can check out and consider as different repositories, as git has the ability to see them as different remotes.

The biggest advantage is that it avoids duplication.

Git hooks

Automation is kewl.

When you're working on projects, it's pretty cool to automate all kinds of tasks during your git workflow.

For example, before allowing a commit to be done, you may wanna run your linter to make sure you're not committing non-style-compliant code.

You could also want to run your unit tests before pushing your changes to your remote repository, to make sure you're not pushing broken content.

Manually doing so is annoying, slow, and prone to error.

Thankfully, git provides the concept of hooks, which is basically a set of executables you can define to be automatically run on different git actions.

Note that git will always ignore non-executable programs, so you can simply disable one by removing the x flag from it.

There are lots of events you can use, around commits, remote interactions, e-mail interactions, and much more.

Setting up a simple web UI over a bare git repository

As shown in my previous article, setting up a bare git repository is dead-easy and much faster and lighter than setting up an entire git-oriented web daemon (such as gitea or gitlab).

Still, it can be nice to be able to browse your git repository through your browser, it's a very convenient feature.

Thankfully, you can easily put and swap web UIs that sit on top of git repositories without having to deploy and setup 28 databases and daemons!

There are a few pretty well-known interfaces:

As a wrap-up

Now, I only showcased uncommon features I personally use a lot, but there is much more to cover; however, this won't be the topic of a third article.

I still strongly invite you to at least check out the list of git manuals, a quick search on mankier will already help you discover a few ones, and I'm sure some will nicely integrate into your workflow.