msfjarvis.dev/content/posts/how-i-use-git/index.md

5.8 KiB

+++ categories = ["git"] date = 2021-08-14 summary = "Everyone uses Git their way. This is how I do it." draft = true slug = "how-i-use-git" tags = ["developer workflow"] title = "How I use Git" +++

Every developer ends up using Git in some way or another these days, whether through the good old CLI or various Git GUI clients or the integrated options in their favorite IDEs. Because there are a myriad ways to use Git, and practically infinite extensibility, everyone internalizes patterns around how they work with Git. A favorite way of merging, a preferred pull strategy, a bunch of shell aliases to save keystrokes, and so on and so forth.

Over time I have also developed habits and patterns, augmented by features present within Git itself as well as external tools that integrate with Git.

This post is going to be a overview of the tools I use with Git, and by extension GitHub, to make my daily workflow more productive.

.gitconfig

The .gitconfig file is essentially the backbone of Git customisation. Any Git-specific setting will reside in one of these config files.

I say files, because Git includes a hierarchy of how Git settings take effect. Within a repository, settings are first looked up in .git/config, and then in $HOME/.gitconfig which allows having per-repository settings as necessary.

My .gitconfig file can be found in my dotfiles here. Most of the settings keys are self-explanatory, the rest I'll go over below.

  • core.pager / interactive.difffilter switch my git diff and git add --patch views to use diff-so-fancy.

diff-so-fancy rendering the diff of a commit

  • pretty.fixes adds a 'pretty' format called fixes which lists commits in the style that is used by the Linux kernel developers to link to the commits which introduced the bug they're fixing in their current commit. It adds a chain of historical reference to identify common bug patterns that are repeatedly occurring, which can then allow teams to devise ways of avoiding them.
➜ git log --pretty=fixes
Fixes: 689a369a3a3d ("Upgrade ConstraintLayout, Material and Timber (#1484)")
Fixes: a82f8dda8607 ("Disable explicit API for tests (#1483)")
Fixes: 70137f31917b ("gradle: switch to our fork of preference testing library (#1481)")
Fixes: 1738364d2fdb ("Make password generator parameter changes reactive (#1480)")
  • alias.branches defines a subcommand that lists all remote branches in order of their last updates. This provides an easy overview of the status of your project's branches.
➜ git branches
 70 minutes ago	fork/develop
 70 minutes ago	origin/HEAD
 70 minutes ago	origin/develop
 3 days ago	origin/release-1.13
 5 days ago	origin/compose-decrypt-screen
 12 days ago	fork/migrate-to-kotest
 2 weeks ago	origin/import-keys
 4 weeks ago	fork/storage-refactor
 8 months ago	origin/api_30_support
 10 months ago	origin/release

From this overview you can see that the develop branch of my fork is synced with the main APS repo, a release was made 3 days ago, and I was trying out Jetpack Compose 5 days ago for one of the app's screens.

  • log.follow will track files through renames, relying on Git's in-built rename detection that it also uses for git cherry-pick and git merge.
# Without `log.follow`
➜ git log --stat 3.txt
commit 4f7bfdf35c1e544b1858e40fabfb26e33a91fde0 (HEAD -> main)
...
 3.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)

# With `log.follow`
➜ git log --stat 3.txt
commit 4f7bfdf35c1e544b1858e40fabfb26e33a91fde0 (HEAD -> main)
...
 2.txt => 3.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)

commit 62a050ddbbad87a0a8317db55dc1121679818825
...
 1.txt => 2.txt | 0
 1 file changed, 0 insertions(+), 0 deletions(-)

commit 005e734a0018b2e8415d2be051c4e2b18e5feee3
...
 1.txt | 1 +
 1 file changed, 1 insertion(+)

hub

Before GitHub had the GitHub CLI, it had hub. hub wraps git and adds a bunch of extra niceties on top such as being able to do git clone <repo> to clone any of your own repositories. The one that I still use though, is hub sync, which fast-forwards all local checkouts of remote branches to the latest state on the remote.

{{< asciinema oHZZ68hPpZdcTmiyI9n9k2XRF >}}

git-absorb

git-absorb is a Git extension that mimics Mercurial's hg absorb extension, which inspects the currently staged changes and tries to look through your recent commits to determine which of them should your changes be amended to. More information on this can be found here

// Add asciinema recording

git-quickfix

git-quickfix is another Git extension, which allows moving commits to a new branch quickly. The most common use case for it is this: Imagine you're working on a feature branch, and notice a small problem that is unrelated to your current branch. git-quickfix would allow you to make a commit on your current branch, then move it to a new branch in just one command.

// Add asciinema recording

gh

gh is GitHub's very own CLI for interacting with their platform. Since my day-to-day work revolves around GitHub, gh is extremely helpful is being able to triage issues, raise PRs, view the status of CI jobs and much more. Definitely a must-have if you're a terminal fiend and use GitHub!