Figure 1 summarizes the relationship between this post (highlighted with a violet border) and the subsequent posts in my Tools blog post series. Click/tap on a node in Figure 1 to navigate to the corresponding post. If you cannot see Figure 1, rotate your smartphone screen to a horizontal (landscape) position.
Thanks to Git, I can sleep💤soundly at night, reassured by the knowledge that all of my progress on all of my ongoing projects is recorded. My progress is not only stored on my local computer, but also on Git repository hosts such as GitHub and GitLab.
Another advantage of using Git is the availability of free web-based editors, such as github.dev, vscode.dev, and Web IDE, that make it possible to modify repo contents via a web browser without the need to keep local copies of repos or have anything installed locally. Cloud-based computing platforms like GitHub Codespaces and GitPod offer the same benefits of web-based editors, but also provide compute for running code and building software, thus enabling remote development on any computer with a web browser.
Before you can benefit from everything GitHub and/or GitLab have to offer, you will need to set up your computer so that you can work locally and/or configure a service like GitHub Codespaces or GitLab Web IDE for remote development in your web browser. In this post, I discuss local development environment setup with the Homebrewpackage manager and repo setup with the GitHub and GitLab CLI.
If you follow along to end of this post, you will have a repo called dotfiles that can be used for Codespaces and GitPod setup. I cover how to set up Codespaces and GitPod in my next blog post, which focuses on the Visual Studio Code (VSCode) and VSCodiumsource-code editors.
If you are not completely satisfied with the terminal that comes with your operating system (OS), you can use Homebrew to install a new terminal. The terminals I use most often are the iTerm2 standalone terminal and the integrated terminal built into my preferred source-code editor VSCodium. Unfortunately, iTerm2 is only for macOS, but there is an abundance of great multi-OS standalone terminals, such as Alacritty, Hyper, Kitty, and Tabby.
After installing Homebrew, you can run brewdoctor in your terminal to confirm that everything is set up correctly. If the brew command is not available, you need to follow the instructions provided after installation to add brew to your PATH variable.
Once Homebrew is ready, you can run the shell code in Example 2 to create a file called Brewfile with the echo shell command and install everything listed in this newly created Brewfile with the brewbundle shell command.
After installing Git, you should go through the First-Time Git Setup or make sure you have a Git configuration file with the correct name and location, either ~/.gitconfig or ~/.config/git/config, where ~ represents the home directory and / is the directory delimiter used in Unixpaths. When configuring Git, I recommend that you set your default editor to VSCode (code) or VSCodium (codium) as shown in Example 3.
If you are curious about how I set up my computer, you can take a look at my Brewfile, .gitconfig, and other configuration files in my setup repo on GitHub and GitLab. In particular, I will highlight my Z shell configuration file (.zshrc) in Section 5.
Authentication
Before we get started, you will need to have created an account on GitHub and/or GitLab. You will need two authentication methods: 1) to sign into github.com or gitlab.com in your browser and 2) to run the gitpush shell command in your terminal. For gitpush to work, you will need either a Personal Access Token (PAT) or a Secure Shell (SSH) key.
Creating a PAT on GitHub or GitLab is easy, but then you must also store your PAT in Keychain Access on Mac or Git Credential Manager on Windows and Linux to avoid having to enter your PAT every time you run gitpush in your terminal. In contrast, setting up an SSH key on GitHub or GitLab requires much more effort but you can set up a single SSH key and reuse it for GitHub, GitLab, and any other service that supports authentication via SSH key.
When I set up a new computer, I create a SSH key using the command in ?@exm-keygen. I can add this key to my SSH agent simply by running ssh-add, but I also
If you enter an empty passphrase when creating your SSH key, then you will not need Keychain Access or Git Credential Manager. frictionless experience by default, whereas PATs are more difficult than need to entered every time your. This major limitation of PATs can be circumvented by storing your PAT in Keychain Access on Mac or Git Credential Manager on Windows and Linux.
The instructions for setting up an SSH key can use your newly created key for both GitHub and GitLab, but if you have more than one account on the same Git repo host, you will need to create a separate key for each account and include each identity file in your ~/.ssh/config file as shown in Example 5.
I can add this key that one SSH key is named ~/.ssh/id_rsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ecdsa_sk, ~/.ssh/id_ed25519, ~/.ssh/id_ed25519_sk, or ~/.ssh/id_dsa.
Iso I can add it to my SSH agent simply by running ssh-add. unless I need to sign into multiple accounts on the same Git repository host.
For example, if I have separate accounts for work and personal projects, I create a separate SSH key for each account and include each identity file in my ~/.ssh/config file as shown in Example 5. If including “AddKeysToAgentyes” does not automatically add your SSH keys to your SSH agent, run ssh-add~/.ssh/USERNAME to add each SSH key.
Of the many authentication methods, passkeys stand out because they can function as both a password and two-factor authentication (2FA), thus combining the two steps in the 2FA sign-in process into one. Passkeys will certainly become more common in the future, especially now that GitHub recently announced its plan to make 2FA mandatory for code contributors.
If you have an identity file in your ~/.ssh/ directory that follows the naming convention, you can add it to your current shell session by running ssh-add. If not, you will need to provide the identity file as an argument, e.g. ssh-add ~/.ssh/USERNAME1.
You can create a repo using the web interface of https://github.com or https://gitlab.com in your browser, but the best way to start a new project is using the CLI for GitHub or GitLab in your terminal. First, run ghauthlogin or glabauthlogin and follow the prompts to authenticate via your web browser or with an authentication token.
After authentication and SSH key setup, you can run the code in either of the code chunks in Example 6 to set up your local and remote repos and create a Quarto website project in the local repo. You can create shell alias that combine all of the repo creation steps like I did in my .zshrc.
cd# start in home directorymkdir USERNAMEcd USERNAMEgh repo create REPONAME --add-readme--clone--publiccd REPONAME
cd# start in home directorymkdir USERNAMEcd USERNAMEglab repo create REPONAME --readme--defaultBranch main --publiccd REPONAMEgit pull origin maingit branch --set-upstream-to=origin/main main
To make it easier to backup my repos on both GitHub and GitLab, I set up each local repo to have two origin remote URLs using the code as shown in Example 7. With this setting, running gitpush in my local repo updates my remote repos on both GitHub and GitLab.
When I want to add or update the content on my site, I go through the steps in the standard Git workflow shown in Figure 2. Every time I “push” a collection of changes called a commit to my maptv.github.io repo on GitHub, a continuous integration (CI) system called GitHub Actions automatically completes the steps required to build and publish my website.
Shell aliases
To make it easier to make incremental changes to my website and frequently release new content, I combined all of the git shell commands in Figure 2 into shell aliases. You can add shell aliases to a shell configuration file like .bashrc or .zshrc on your computer to shorten one or more commands and any associated command arguments.
The gitcommit aliases in the .zshrc file in my setup repo on GitHub and GitLab target different groups of files for inclusion in the next commit. For example, cmp targets staged files, camp targets tracked files, a.cmp targets files in the current directory, and aacmp targets files in the repo.
Example 8 shows the aacmp alias as an example of the shell alias syntax. The mnemonic device for this alias is add all, commit with a message, and push.
Aliases like aacmp allow me to enter free-form commit messages directly on the command line without quotes, e.g. aacmpeditfirstpost. If you decide to try one of these aliases, please exercise extreme caution as any un-escaped or un-quoted metacharacters may yield surprising effects instead of being included verbatim in the commit message, e.g. * is replaced by all of the file and directory names in the current directory!
If no commit message is provided after the aliases, a generic commit message is created that includes the change type and name of each changed file. In Section 5.2, I describe how I used this generic commit message approach to further simplify the Git workflow.
Keybindings
An alternative to a shell alias that combines git commands is to use a keyboard shortcut in a Git Graphical User Interface (GUI) such as GitHub Desktop or the Git interface in a code editor like VSCode, VSCodium, or RStudio. I use keyboard shortcuts in VSCode and VSCodium to send shell commands to the integrated terminal without moving my focus away from the files I am editing.
I created different shortcuts to control which files are included in each commit: ⌥⇧F for the current file only, ⌥⇧S for already staged files, ⌥⇧T for all tracked files, and ⌥⇧U for all files including untracked files. I also have keyboard shortcuts that affect a specific directory (and all of its subdirectories): ⌥⇧D for the current file’s directory, ⌥⇧. for shell’s current directory, ⌥⇧C for the current working directory according to VSCode/VSCodium, ⌥⇧W for the Workspace directory.
Example 9 displays the ⌥⇧F shortcut as an example of the VSCode/VSCodium shortcut syntax. This shortcut uses the escape code for the return key (\u000D) to run several git commands and predefined variables to insert the absolute (${file}) and relative (${relativeFile}) path to the currently open file.
If you want to set up similar shortcuts for yourself, take a look at my keybindings.json in my setup repo on GitHub and GitLab. As you create keyboard shortcuts, please be mindful of keybinding conflicts that may arise.
To set up a keyboard shortcut that runs a series of steps rather than a single line of shell code, I suggest you use the VSCode/VSCodium Tasks mechanism, a system designed to automatesoftware build tasks. The default keyboard shortcut to run all tasks in a local or globaltask.json file is ⌃⇧B on Linux/Windows or ⌘⇧B on Mac (mnemonic: B is for Build), but you can bind other shortcuts to specific tasks.
If you use a text editor like Vim or Emacs, you can create keybindings for Vim plugins like fugitive or Emacs packages like magit that run through the entire Git workflow. Example 10 shows the Vim+fugitive equivalent of my ⌥⇧F VSCode/VSCodium keybinding.
The drawback of my keyboard shortcut approach for the Git workflow is that it produces generic commit messages that are no very informative. Anyone reading the messages will not be able to tell what changes were made and more importantly why the changes were made.
To automatically generate commit messages based on the currently staged changes, we can use a Large Language Model (LLM). Generative artificial intelligence models like LLMs tend to be large in size and have atypical computational requirements, so I will save my adventures with LLMs for a different post.
I really enjoy using Git, especially with shell aliases in my terminal and keyboard shortcuts in my favorite text editors. If we ever collaborate on a project together, you can be sure that I will insist on using Git!
---title: Gitdraft: trueauthor: - name: Martin Laptev url: https://maptv.github.iodate: last-modifiedimage: horst_git-hug.pngcategories: - tool - gitcitation: url: https://maptv.github.io/blog/git issued: 2024 accessed: 2024date-format: xformat: html: include-after-body: - ../../asset/cite.html - ../../asset/style.html - ../../asset/stamp.html - ../../asset/tooltip.htmlfilters: - ../../asset/date.lua - include-code-files---## [TL;DR]{.underline .blue data-bs-toggle="tooltip" data-bs-title="too long; didn't read"}In this blog post, I show how to use the [Git](https://en.wikipedia.org/wiki/Git#:~:text=Git%20(/%C9%A1%C9%AAt/)%5B8%5D%20is%20a%20distributed%20version%20control%20system%5B9%5D%20that%20tracks%20changes%20in%20any%20set%20of%20computer%20files%2C%20usually%20used%20for%20coordinating%20work%20among%20programmers%20who%20are%20collaboratively%20developing%20source%20code%20during%20software%20development.) [version control](https://en.wikipedia.org/wiki/Version_control#:~:text=version%20control%20(also%20known%20as%20revision%20control%2C%20source%20control%2C%20or%20source%20code%20management)%20is%20a%20class%20of%20systems%20responsible%20for%20managing%20changes%20to%20computer%20programs%2C%20documents%2C%20large%20web%20sites%2C%20or%20other%20collections%20of%20information.) system and the [command line interfaces](https://en.wikipedia.org/wiki/Command-line_interface#:~:text=A%20command%2Dline%20interface%20(CLI)%20is%20a%20means%20of%20interacting%20with%20a%20computer%20program%20by%20inputting%20lines%20of%20text%20called%20command%2Dlines.) (CLIs) for the [GitHub](https://github.com) and [GitLab](https://gitlab.com) Git [repository hosts](https://en.wikipedia.org/wiki/Git#:~:text=Git%20repository%20services%2C%20including%20GitHub%2C%20SourceForge%2C%20Bitbucket%20and%20GitLab.%5B) to create a Git [repository](https://en.wikipedia.org/wiki/Repository_(version_control)#:~:text=In%20version%20control%20systems%2C%20a%20repository%20is%20a%20data%20structure%20that%20stores%20metadata%20for%20a%20set%20of%20files%20or%20directory%20structure.) that contains setup files for the [Codespaces](https://github.com/features/codespaces) and [GitPod](https://www.gitpod.io)[computing platforms](https://en.wikipedia.org/wiki/Computing_platform#:~:text=A%20computing%20platform%2C%20digital%20platform%2C%5B1%5D%20or%20software%20platform%20is%20an%20environment%20in%20which%20software%20is%20executed.).## Navigation Chart@fig-navchart summarizes the relationship between this post (highlighted with a [violet]{style="color: #88f;"} border) and the subsequent posts in my [Tools](..#category=tool) blog post series. Click/tap on a node in @fig-navchart to navigate to the corresponding post. If you cannot see @fig-navchart, rotate your smartphone screen to a horizontal (landscape) position.```{mermaid}%%| column: margin%%| label: fig-navchart%%| fig-cap: Tools series navigation chartflowchart TB A[Git]-->B[VSCode]-->C[Quarto] C-->D[Observable] C-->E[Jupyter] C-->F[Knitr] click A "../git" click B "../vscode" click C "../quarto" click D "../observable" click E "../jupyter" click F "../knitr" style A stroke:#99f,stroke-width:5px```## Introduction {#sec-intro}[Git](https://en.wikipedia.org/wiki/Git#:~:text=Git%20(/%C9%A1%C9%AAt/)%5B8%5D%20is%20a%20distributed%20version%20control%20system%5B9%5D%20that%20tracks%20changes%20in%20any%20set%20of%20computer%20files%2C%20usually%20used%20for%20coordinating%20work%20among%20programmers%20who%20are%20collaboratively%20developing%20source%20code%20during%20software%20development.) is a [version control](https://en.wikipedia.org/wiki/Version_control#:~:text=version%20control%20(also%20known%20as%20revision%20control%2C%20source%20control%2C%20or%20source%20code%20management)%20is%20a%20class%20of%20systems%20responsible%20for%20managing%20changes%20to%20computer%20programs%2C%20documents%2C%20large%20web%20sites%2C%20or%20other%20collections%20of%20information.) system developed by [Linux](https://en.wikipedia.org/wiki/Linux#:~:text=Linux%20(/%CB%88l%C9%AAn%CA%8Aks/%20LIN%2Duuks)%5B11%5D%20is%20a%20family%20of%20open%2Dsource%20Unix%2Dlike%20operating%20systems%20based%20on%20the%20Linux%20kernel%2C%5B12%5D%20an%20operating%20system%20kernel%20first%20released%20on%20September%2017%2C%201991%2C%20by%20Linus%20Torvalds.) creator [Linus Torvalds](https://en.wikipedia.org/wiki/Linus_Torvalds#:~:text=Linus%20Benedict%20Torvalds%20(,control%20system%20Git.)). Since its first release in [`2005+037`]{.underline .blue data-bs-toggle="tooltip" data-bs-title="2005-04-07"}, Git has largely replaced other version control systems and is used by 93% of [software](https://en.wikipedia.org/wiki/Software#:~:text=Software%20is%20a%20set%20of%20computer%20programs%20and%20associated%20documentation%20and%20data.) developers worldwide, according to [survey results](https://stackoverflow.blog/2023/01/09/beyond-git-the-other-version-control-systems-developers-use/#:~:text=Our%20developer%20survey%20found%2093%25%20of%20developers%20use%20Git.) published by [StackOverflow](https://stackoverflow.com/tour) on [`2022+314`]{.underline .blue data-bs-toggle="tooltip" data-bs-title="2023-01-09"}.Thanks to Git, I can sleep💤soundly at night, reassured by the knowledge that all of my progress on all of my ongoing projects is recorded. My progress is not only stored on my local computer, but also on [Git repository hosts](https://en.wikipedia.org/wiki/Git#:~:text=Git%20repository%20services%2C%20including%20GitHub%2C%20SourceForge%2C%20Bitbucket%20and%20GitLab.%5B) such as [GitHub](https://en.wikipedia.org/wiki/GitHub#:~:text=GitHub%2C%20Inc.%20(/%CB%88%C9%A1%C9%AAth%CA%8Cb/%5Ba%5D)%20is%20a%20platform%20and%20cloud%2Dbased%20service%20for%20software%20development%20and%20version%20control%2C%20allowing%20developers%20to%20store%20and%20manage%20their%20code.) and [GitLab](https://en.wikipedia.org/wiki/GitLab).A Git [repository](https://en.wikipedia.org/wiki/Repository_(version_control)#:~:text=In%20version%20control%20systems%2C%20a%20repository%20is%20a%20data%20structure%20that%20stores%20metadata%20for%20a%20set%20of%20files%20or%20directory%20structure.) (repo) is a [directory](https://en.wikipedia.org/wiki/Directory_(computing)#:~:text=a%20directory%20is%20a%20file%20system%20cataloging%20structure%20which%20contains%20references%20to%20other%20computer%20files%2C%20and%20possibly%20other%20directories.) that tracks the changes made to its contents. For more information on GitHub, the largest Git repo host, take a look at the ["GitHub for supporting, reusing, contributing, and failing safely"](https://openscapes.org/blog/2022-05-27-github-illustrated-series/) post by [Allison Horst](https://allisonhorst.com) and [Julie Lowndes](https://jules32.github.io) on the [Openscapes](https://openscapes.org/)[blog](https://openscapes.org/blog).GitHub and GitLab do not only host repos, but also websites via [GitHub Pages](https://quarto.org/docs/publishing/github-pages.html#render-to-docs) and [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/). In addition to providing basic web hosting for free, GitHub and GitLab offer free access to [continuous integration](https://en.wikipedia.org/wiki/Continuous_integration#:~:text=In%20software%20engineering%2C%20continuous%20integration%20(CI)%20is%20the%20practice%20of%20merging%20all%20developers%27%20working%20copies%20to%20a%20shared%20mainline%20several%20times%20a%20day.) (CI) systems called [GitHub Actions](https://docs.github.com/en/actions) and [GitLab CI/CD](https://docs.gitlab.com/ee/ci) that can automatically [build](https://en.wikipedia.org/wiki/Software_build) and [deploy](https://en.wikipedia.org/wiki/Software_deployment#:~:text=Software%20deployment%20is%20all%20of%20the%20activities%20that%20make%20a%20software%20system%20available%20for%20use.) software.Another advantage of using Git is the availability of free web-based editors, such as [github.dev](https://github.dev/github/dev), [vscode.dev](https://vscode.dev), and [Web IDE](https://docs.gitlab.com/ee/user/project/web_ide/), that make it possible to modify repo contents via a [web browser](https://en.wikipedia.org/wiki/Web_browser#:~:text=A%20web%20browser%20is%20an%20application%20for%20accessing%20websites%20and%20the%20Internet.%5B) without the need to keep local copies of repos or have anything installed locally. [Cloud](https://en.wikipedia.org/wiki/Cloud_computing#:~:text=Cloud%20computing%5B1%5D%20is%20the%20on%2Ddemand%20availability%20of%20computer%20system%20resources%2C%20especially%20data%20storage%20(cloud%20storage)%20and%20computing%20power%2C%20without%20direct%20active%20management%20by%20the%20user.)-based computing platforms like [GitHub Codespaces](https://github.com/features/codespaces) and [GitPod](https://www.gitpod.io) offer the same benefits of web-based editors, but also provide compute for running code and building software, thus enabling remote development on any computer with a web browser.Before you can benefit from everything GitHub and/or GitLab have to offer, you will need to set up your computer so that you can work locally and/or configure a service like GitHub Codespaces or [GitLab Web IDE](https://docs.gitlab.com/ee/user/project/web_ide) for remote development in your [web browser](https://en.wikipedia.org/wiki/Web_browser#:~:text=A%20web%20browser%20is%20an%20application%20for%20accessing%20websites%20and%20the%20Internet.%5B). In this post, I discuss local development environment setup with the [Homebrew](https://brew.sh)[package manager](https://en.wikipedia.org/wiki/Package_manager#:~:text=A%20package%20manager%20or%20package%2Dmanagement%20system%20is%20a%20collection%20of%20software%20tools%20that%20automates%20the%20process%20of%20installing%2C%20upgrading%2C%20configuring%2C%20and%20removing%20computer%20programs%20for%20a%20computer%20in%20a%20consistent%20manner.) and repo setup with the GitHub and GitLab CLI.If you follow along to end of this post, you will have a repo called `dotfiles` that can be used for Codespaces and GitPod setup. I cover how to set up Codespaces and GitPod in my [next blog post](../vscode), which focuses on the [Visual Studio Code](https://code.visualstudio.com) (VSCode) and [VSCodium](https://vscodium.com)[source-code editors](https://en.wikipedia.org/wiki/Source-code_editor#:~:text=A%20source%2Dcode%20editor%20is%20a%20text%20editor%20program%20designed%20specifically%20for%20editing%20source%20code%20of%20computer%20programs.).## Setup {#sec-setup}### Homebrew {#sec-setup-brew}[Linux](https://en.wikipedia.org/wiki/Linux#:~:text=Linux%20(/%CB%88l%C9%AAn%CA%8Aks/%20LIN%2Duuks)%5B11%5D%20is%20a%20family%20of%20open%2Dsource%20Unix%2Dlike%20operating%20systems), [macOS](https://en.wikipedia.org/wiki/MacOS#:~:text=macOS%20(/%CB%8Cm%C3%A6ko%CA%8A%CB%88%C9%9Bs/%3B%5B6%5D%20previously%20OS%C2%A0X%20and%20originally%20Mac%C2%A0OS%C2%A0X)%20is%20an%20operating%20system%20developed%20and%20marketed%20by%20Apple%20Inc.%20since%202001.), or [Windows Subsystem for Linux](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux#:~:text=Windows%20Subsystem%20for%20Linux%20(WSL)%20is%20a%20feature%20of%20Windows%20that%20allows%20developers%20to%20run%20a%20Linux%20environment%20without%20the%20need%20for%20a%20separate%20virtual%20machine%20or%20dual%20booting.) (WSL) users can install everything needed to work through all of the examples in this blog post via the Homebrew](https://brew.sh) package manager. First, [install Homebrew](https://brew.sh/#install) itself with the latest [`.pkg` installer](https://github.com/Homebrew/brew/releases) for macOS or by running the @exm-brew [Unix](https://en.wikipedia.org/wiki/Unix#:~:text=Unix%20(/%CB%88ju%CB%90n%C9%AAks/%2C%20YOO%2Dniks%3B%20trademarked%20as%20UNIX)%20is%20a%20family%20of%20multitasking%2C%20multi%2Duser%20computer%20operating%20systems) [shell](https://en.wikipedia.org/wiki/Unix_shell#:~:text=A%20Unix%20shell%20is%20a%20command%2Dline%20interpreter%20or%20shell%20that%20provides%20a%20command%20line%20user%20interface%20for%20Unix%2Dlike%20operating%20systems.) code in your [terminal](https://en.wikipedia.org/wiki/Terminal_emulator#:~:text=A%20terminal%20emulator%2C%20or%20terminal%20application%2C%20is%20a%20computer%20program%20that%20emulates%20a%20video%20terminal%20within%20some%20other%20display%20architecture.).::: {#exm-brew}``` sh/bin/bash-c"$(curl-fsSL https://\raw.githubusercontent.com/Homebrew/\install/HEAD/install.sh)"```:::If you are not completely satisfied with the terminal that comes with your [operating system](https://en.wikipedia.org/wiki/Operating_system#:~:text=An%20operating%20system%20(OS)%20is%20system%20software%20that%20manages%20computer%20hardware%20and%20software%20resources%2C%20and%20provides%20common%20services%20for%20computer%20programs.) (OS), you can use Homebrew to install a new terminal. The terminals I use most often are the [iTerm2](https://formulae.brew.sh/cask/iterm2#default) standalone terminal and the integrated terminal built into my preferred [source-code editor](https://en.wikipedia.org/wiki/Source-code_editor#:~:text=A%20source%2Dcode%20editor%20is%20a%20text%20editor%20program%20designed%20specifically%20for%20editing%20source%20code%20of%20computer%20programs.) VSCodium. Unfortunately, iTerm2 is only for macOS, but there is an abundance of great multi-OS standalone terminals, such as [Alacritty](https://formulae.brew.sh/cask/alacritty#default), [Hyper](https://formulae.brew.sh/cask/hyper#default), [Kitty](https://formulae.brew.sh/cask/kitty#default), and [Tabby](https://formulae.brew.sh/cask/tabby#default).After installing Homebrew, you can run `brew``doctor` in your terminal to confirm that everything is set up correctly. If the `brew` command is not available, you need to follow the instructions provided after installation to add `brew` to your [PATH variable](https://en.wikipedia.org/wiki/PATH_(variable)#:~:text=PATH%20is%20an%20environment%20variable%20on%20Unix%2Dlike%20operating%20systems%2C%20DOS%2C%20OS/2%2C%20and%20Microsoft%20Windows%2C%20specifying%20a%20set%20of%20directories%20where%20executable%20programs%20are%20located.).Once Homebrew is ready, you can run the shell code in @exm-echo to create a file called `Brewfile` with the [`echo`](https://en.wikipedia.org/wiki/Echo_(command)#:~:text=echo%20is%20a%20command%20that%20outputs%20the%20strings%20that%20are%20passed%20to%20it%20as%20arguments.) shell command and install everything listed in this newly created [`Brewfile`](https://homebrew-file.readthedocs.io/en/latest/usage.html) with the `brew``bundle` shell command.::: {#exm-echo}``` {.sh}echo 'brew "gh"\nbrew "git"brew "glab"\ncask "github"' > Brewfilebrew bundle```:::The `Brewfile` created by the shell code in @exm-echo installs:- Git,- the [command line interfaces](https://en.wikipedia.org/wiki/Command-line_interface#:~:text=A%20command%2Dline%20interface%20(CLI)%20is%20a%20means%20of%20interacting%20with%20a%20computer%20program%20by%20inputting%20lines%20of%20text%20called%20command%2Dlines.) (CLIs) for - [GitHub](https://cli.github.com) and - [GitLab](https://docs.gitlab.com/ee/editor_extensions/gitlab_cli/), and- the [GitHub Desktop](https://git-scm.com/downloads/guis#:~:text=iOS-,GitHub%20Desktop,-Platforms%3A%20Mac) Git [Graphical User Interface](https://en.wikipedia.org/wiki/Graphical_user_interface#:~:text=A%20graphical%20user%20interface%2C%20or%20GUI%20(/%CB%88%C9%A1u%CB%90i/%5B1%5D%5B2%5D%20GOO%2Dee)%2C%20is%20a%20form%20of%20user%20interface%20that%20allows%20users%20to%20interact%20with%20electronic%20devices%20through%20graphical%20icons%20and%20audio%20indicators%20such%20as%20primary%20notation.) (GUI).After installing Git, you should go through the [First-Time Git Setup](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup) or make sure you have a Git configuration file with the correct name and location, either `~/.gitconfig` or `~/.config/git/config`, where [`~`](https://en.wikipedia.org/wiki/Home_directory#:~:text=the%20~%20(tilde)%20character%20is%20equivalent%20to%20specifying%20the%20current%20user%27s%20home%20directory) represents the [home directory](https://en.wikipedia.org/wiki/Home_directory#:~:text=A%20home%20directory%20is%20a%20file%20system%20directory%20on%20a%20multi%2Duser%20operating%20system%20containing%20files%20for%20a%20given%20user%20of%20the%20system.) and `/` is the [directory delimiter](https://en.wikipedia.org/wiki/Path_(computing)#:~:text=Around%201970%2C%20Unix%20introduced%20the%20slash%20character%20(%22/%22)%20as%20its%20directory%20separator.) used in [Unix](https://en.wikipedia.org/wiki/Unix#:~:text=Unix%20(/%CB%88ju%CB%90n%C9%AAks/%2C%20YOO%2Dniks%3B%20trademarked%20as%20UNIX)%20is%20a%20family%20of%20multitasking%2C%20multi%2Duser%20computer%20operating%20systems) [paths](https://en.wikipedia.org/wiki/Path_(computing)#:~:text=A%20path%20is%20a%20string%20of%20characters%20used%20to%20uniquely%20identify%20a%20location%20in%20a%20directory%20structure.). When configuring Git, I recommend that you set your [default editor](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup#_editor) to VSCode (`code`) or VSCodium (`codium`) as shown in @exm-editor.::: {#exm-editor}::: panel-tabset#### Shell```shgit config --global core.editor "codium --wait"```#### `.gitconfig````toml[core] editor = codium --wait```::::::If you are curious about how I set up my computer, you can take a look at my [`Brewfile`](https://github.com/maptv/setup/blob/main/Brewfile), [`.gitconfig`](https://github.com/maptv/setup/blob/main/.gitconfig), and other configuration files in my `setup` repo on [GitHub](https://github.com/maptv/setup) and [GitLab](https://gitlab.com/maptv/setup). In particular, I will highlight my [Z shell](https://en.wikipedia.org/wiki/Z_shell#:~:text=The%20Z%20shell%20(Zsh)%20is%20a%20Unix%20shell%20that%20can%20be%20used%20as%20an%20interactive%20login%20shell%20and%20as%20a%20command%20interpreter%20for%20shell%20scripting.) configuration file (`.zshrc`) in @sec-workflow.### Authentication {#sec-setup-auth}Before we get started, you will need to have created an account on [GitHub](https://github.com/signup) and/or [GitLab](https://gitlab.com/users/sign_up). You will need two authentication methods: 1) to sign into [github.com](https://github.com) or [gitlab.com](https://gitlab.com) in your browser and 2) to run the `git``push` shell command in your terminal. For `git``push` to work, you will need either a [Personal Access Token](https://en.wikipedia.org/wiki/Personal_access_token#:~:text=a%20personal%20access%20token%20(or%20PAT)%20is%20a%20string%20of%20characters%20that%20can%20be%20used%20to%20authenticate%20a%20user%20when%20accessing%20a%20computer%20system%20instead%20of%20the%20usual%20password.) (PAT) or a [Secure Shell](https://en.wikipedia.org/wiki/Secure_Shell#:~:text=The%20Secure%20Shell%20Protocol%20(SSH)%20is%20a%20cryptographic%20network%20protocol%20for%20operating%20network%20services%20securely%20over%20an%20unsecured%20network.) (SSH) [key](https://en.wikipedia.org/wiki/Public-key_cryptography#:~:text=Public%2Dkey%20cryptography%2C%20or%20asymmetric%20cryptography%2C%20is%20the%20field%20of%20cryptographic%20systems%20that%20use%20pairs%20of%20related%20keys.).Creating a PAT on [GitHub](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic) or [GitLab](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token) is easy, but then you must also store your PAT in [Keychain Access](https://docs.github.com/en/get-started/getting-started-with-git/updating-credentials-from-the-macos-keychain) on Mac or [Git Credential Manager](https://github.blog/2022-04-07-git-credential-manager- authentication-for-everyone) on Windows and Linux to avoid having to enter your PAT every time you run `git``push` in your terminal. In contrast, setting up an SSH key on [GitHub](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account#about-addition-of-ssh-keys-to-your-account) or [GitLab](https://docs.gitlab.com/ee/user/ssh.html#generate-an-ssh-key-pair) requires much more effort but you can set up a single SSH key and reuse it for GitHub, GitLab, and any other service that supports authentication via SSH key.When I set up a new computer, I create a SSH key using the command in @exm-keygen. I can add this key to my SSH agent simply by running `ssh-add`, but I also ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C $(uname -n)_$(sysctl hw.model | cut -f2 -d\ )I use the If you enter an empty passphrase when creating your SSH key, then you will not need Keychain Access or Git Credential Manager. frictionless experience by default, whereas PATs are more difficult than need to entered every time your. This major limitation of PATs can be circumvented by storing your PAT in [Keychain Access](https://docs.github.com/en/get-started/getting-started-with-git/updating-credentials-from-the-macos-keychain) on Mac or [Git Credential Manager](https://github.blog/2022-04-07-git-credential-manager- authentication-for-everyone) on Windows and Linux.The instructions for setting up an SSH key can use your newly created key for both GitHub and GitLab, but if you have more than one account on the same Git repo host, you will need to create a separate key for each account and include each identity file in your `~/.ssh/config` file as shown in @exm-ssh.I can add this key that one SSH key is named `~/.ssh/id_rsa`, `~/.ssh/id_ecdsa`, `~/.ssh/id_ecdsa_sk`, `~/.ssh/id_ed25519`, `~/.ssh/id_ed25519_sk`, or `~/.ssh/id_dsa.`Iso I can [add it to my SSH agent](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent?platform=mac#adding-your-ssh-key-to-the-ssh-agent) simply by running `ssh-add`. unless I need to sign into multiple accounts on the same Git repository host.For example, if I have separate accounts for work and personal projects, I create a separate SSH key for each account and include each identity file in my `~/.ssh/config` file as shown in @exm-ssh. If including "`AddKeysToAgent``yes`" does not automatically add your SSH keys to your SSH agent, run `ssh-add``~/.ssh/USERNAME` to add each SSH key.::: {#exm-ssh}```ssh-config {filename="~/.ssh/config"}Host github-WORKUSERNAME AddKeysToAgent yes HostName github.com IdentityFile ~/.ssh/WORKUSERNAME IdentitiesOnly yesHost github-PERSONALUSERNAME AddKeysToAgent yes HostName github.com IdentityFile ~/.ssh/PERSONALUSERNAME IdentitiesOnly yes```:::Of the many [authentication methods](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github#about-authentication-to-github), passkeys stand out because they can function as both a password and [two-factor authentication](https://en.wikipedia.org/wiki/Multi-factor_authentication#:~:text=two%2Dfactor%20authentication%2C%20or%202FA%2C%20along%20with%20similar%20terms%20is%20an%20electronic%20authentication%20method%20in%20which%20a%20user%20is%20granted%20access%20to%20a%20website%20or%20application%20only%20after%20successfully%20presenting%20two%20or%20more%20pieces%20of%20evidence%20(or%20factors)%20to%20an%20authentication%20mechanism.) (2FA), thus combining the two steps in the 2FA sign-in process into one. Passkeys will certainly become more common in the future, especially now that GitHub recently announced its plan to make [2FA mandatory](https://github.blog/2023-03-09-raising-the-bar-for-software-security-github-2fa-begins-march-13) for code contributors.When authenticating via SSH, we use SSH [URLs](https://en.wikipedia.org/wiki/URL#:~:text=A%20Uniform%20Resource%20Locator%20(URL)%2C%20colloquially%20known%20as%20an%20address%20on%20the%20Web), such as <git@github.com:maptv/dotfiles>.With PATs, we use [HTTPS](https://en.wikipedia.org/wiki/HTTPS) URLs such as <https://github.com/maptv/dotfiles>, instead of the ::: {#exm-ssh} ```ssh-config {filename="~/.ssh/config"}Host github-USERNAME1 HostName github.com IdentityFile ~/.ssh/USERNAME1 IdentitiesOnly yesHost github-USERNAME2 HostName github.com IdentityFile ~/.ssh/USERNAME2 IdentitiesOnly yes```:::If you have an identity file in your `~/.ssh/` directory that follows the [naming convention](https://man7.org/linux/man-pages/man1/ssh-add.1.html#:~:text=~/.ssh/id_rsa%2C%20~/.ssh/id_ecdsa%2C%20~/.ssh/id_ecdsa_sk%2C%0A%20%20%20%20%20~/.ssh/id_ed25519%2C%20~/.ssh/id_ed25519_sk%2C%20and%20~/.ssh/id_dsa), you can add it to your current shell session by running `ssh-add`. If not, you will need to provide the identity file as an argument, e.g. `ssh-add ~/.ssh/USERNAME1`.You can create a repo using the web interface of <https://github.com> or <https://gitlab.com> in your browser, but the best way to start a new project is using the CLI for [GitHub](https://cli.github.com) or [GitLab](https://docs.gitlab.com/ee/editor_extensions/gitlab_cli/) in your [terminal](https://en.wikipedia.org/wiki/Terminal_emulator). First, run `gh``auth``login` or `glab``auth``login` and follow the prompts to authenticate via your web browser or with an [authentication token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).The GitHub CLI allows you to add an SSH key to your account during or [after authentication](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account?tool=cli#adding-a-new-ssh-key-to-your-account). The GitLab CLI does not handle SSH keys during authentication, but has a similar command for [adding an SSH key to your GitLab account](https://gitlab.com/gitlab-org/cli/-/blob/main/docs/source/ssh-key/add.md).### Repository {#sec-setup-repo}After authentication and SSH key setup, you can run the code in either of the code chunks in @exm-git to set up your local and remote repos and create a Quarto website project in the local repo. You can create shell alias that combine all of the repo creation steps like I did in my [`.zshrc`](https://github.com/maptv/setup/blob/0bd5898908974746fa55e7e8f19a36859040b6ca/.zshrc#L630).::: {#exm-git}::: panel-tabset#### GitHub``` shcd# start in home directorymkdir USERNAMEcd USERNAMEgh repo create REPONAME --add-readme--clone--publiccd REPONAME```#### GitLab``` shcd# start in home directorymkdir USERNAMEcd USERNAMEglab repo create REPONAME --readme--defaultBranch main --publiccd REPONAMEgit pull origin maingit branch --set-upstream-to=origin/main main```::::::To make it easier to backup my repos on both GitHub and GitLab, I set up each local repo to have two `origin` remote URLs using the code as shown in @exm-remote. With this setting, running `git``push` in my local repo updates my remote repos on both GitHub and GitLab.::: {#exm-remote}``` shgit remote add lab git@gitlab.com:maptv/maptv.gitlab.iogit remote add hub git@github.com:maptv/maptv.github.iogit remote set-url --add origin $(git remote get-url lab)```:::## Git workflow {#sec-workflow}When I want to add or update the content on my site, I go through the steps in the standard Git workflow shown in @fig-git. Every time I "push" a collection of changes called a [commit](https://en.wikipedia.org/wiki/Commit_(version_control)#:~:text=In%20version%20control%20systems%2C%20a%20commit%20is%20an%20operation%20which%20sends%20the%20latest%20changes%20of%20the%20source%20code%20to%20the%20repository%2C%20making%20these%20changes%20part%20of%20the%20head%20revision%20of%20the%20repository.) to my [maptv.github.io](https://github.com/maptv.github.io) repo on GitHub, a [continuous integration](https://en.wikipedia.org/wiki/Continuous_integration#:~:text=In%20software%20engineering%2C%20continuous%20integration%20(CI)%20is%20the%20practice%20of%20merging%20all%20developers%27%20working%20copies%20to%20a%20shared%20mainline%20several%20times%20a%20day.) (CI) system called [GitHub Actions](https://docs.github.com/en/actions) automatically completes the steps required to build and publish my website.```{mermaid fig-align="center"}%%| label: fig-git%%| fig-cap: Git workflow%%| fig-align: center%%| fig-width: 9flowchart LR A[working<br/>directory]-.git<br/>add.->B{{staging<br/>area}}-.git<br/>commit.->C([local<br/>repo])-.git<br/>push.->D(remote<br/>repo)```### Shell aliases {#sec-workflow-alias}To make it easier to make incremental changes to my website and frequently release new content, I combined all of the `git` shell commands in @fig-git into shell [aliases](https://en.wikipedia.org/wiki/Alias_(command)#:~:text=In%20computing%2C%20alias%20is%20a%20command%20in%20various%20command%2Dline%20interpreters%20(shells)%2C%20which%20enables%20a%20replacement%20of%20a%20word%20by%20another%20string.). You can add shell aliases to a [shell configuration file](https://en.wikipedia.org/wiki/Unix_shell#:~:text=The%20%22rc%22%20suffix%20on%20some%20Unix%20configuration%20files%20(for%20example%2C%20%22.vimrc%22)%2C%20is%20a%20remnant%20of%20the%20RUNCOM%20ancestry%20of%20Unix%20shells.) like `.bashrc` or `.zshrc` on your computer to shorten one or more commands and any associated command [arguments](https://en.wikipedia.org/wiki/Command-line_interface#Arguments:~:text=A%20command%2Dline%20argument%20or%20parameter%20is%20an%20item%20of%20information%20provided%20to%20a%20program%20when%20it%20is%20started.).The `git``commit` aliases in the `.zshrc` file in my `setup` repo on [GitHub](https://github.com/maptv/setup) and [GitLab](https://gitlab.com/maptv/setup) target different groups of files for inclusion in the next commit. For example, `cmp` targets [staged](https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F#:~:text=Staged%20means%20that%20you%20have%20marked%20a%20modified%20file%20in%20its%20current%20version%20to%20go%20into%20your%20next%20commit%20snapshot.) files, `camp` targets [tracked](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#:~:text=Tracked%20files%20are%20files%20that%20were%20in%20the%20last%20snapshot%2C%20as%20well%20as%20any%20newly%20staged%20files) files, `a.cmp` targets files in the current directory, and `aacmp` targets files in the repo.@exm-alias shows the `aacmp` alias as an example of the shell alias syntax. The mnemonic device for this alias is **a**dd **a**ll, **c**ommit with a **m**essage, and **p**ush.::: {#exm-alias}``` {.sh filename=".zshrc"}alias aacmp="func() { git add --all && git commit --message \ \"$(echo '${*:-$(echo $(git diff --name-status --cached \ | tr "[:space:]" " "))}')\" && git push; }; func"```:::Aliases like `aacmp` allow me to enter free-form [commit messages](https://en.wikipedia.org/wiki/Commit_(version_control)#:~:text=git%20commit%20%2Dm%20%27-,commit%20message,-%27) directly on the command line without quotes, e.g. `aacmp``edit``first``post`. If you decide to try one of these aliases, please exercise extreme caution as any un-[escaped](https://en.wikipedia.org/wiki/Escape_character#:~:text=an%20escape%20character%20is%20a%20character%20that%20invokes%20an%20alternative%20interpretation%20on%20the%20following%20characters%20in%20a%20character%20sequence.) or un-quoted [metacharacters](https://en.wikipedia.org/wiki/Metacharacter#:~:text=A%20metacharacter%20is%20a%20character%20that%20has%20a%20special%20meaning%20to%20a%20computer%20program%2C%20such%20as%20a%20shell%20interpreter) may yield surprising effects instead of being included verbatim in the commit message, e.g. `*` is replaced by all of the file and directory names in the current directory!If no commit message is provided after the aliases, a generic commit message is created that includes the [change type](https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---diff-filterACDMRTUXB82308203) and name of each changed file. In @sec-workflow-key, I describe how I used this generic commit message approach to further simplify the Git workflow.### Keybindings {#sec-workflow-key}An alternative to a shell alias that combines `git` commands is to use a keyboard shortcut in a [Git Graphical User Interface (GUI)](https://git-scm.com/downloads/guis#:~:text=iOS-,GitHub%20Desktop,-Platforms%3A%20Mac) such as [`GitHub Desktop`](https://desktop.github.com) or the Git interface in a [code editor](https://en.wikipedia.org/wiki/Source-code_editor#:~:text=A%20source%2Dcode%20editor%20is%20a%20text%20editor%20program%20designed%20specifically%20for%20editing%20source%20code%20of%20computer%20programs.) like VSCode, VSCodium, or RStudio. I use keyboard shortcuts in VSCode and VSCodium to send shell commands to the integrated terminal without moving my focus away from the files I am editing.I created different shortcuts to control which files are included in each commit: ⌥⇧F for the current file only, ⌥⇧S for already [staged](https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F#:~:text=Staged%20means%20that%20you%20have%20marked%20a%20modified%20file%20in%20its%20current%20version%20to%20go%20into%20your%20next%20commit%20snapshot.) files, ⌥⇧T for all [tracked files](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#:~:text=Tracked%20files%20are%20files%20that%20were%20in%20the%20last%20snapshot%2C%20as%20well%20as%20any%20newly%20staged%20files), and ⌥⇧U for all files including [untracked files](https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#:~:text=Untracked%20files%20are%20everything%20else%E2%80%89%E2%80%94%E2%80%89any%20files%20in%20your%20working%20directory%20that%20were%20not%20in%20your%20last%20snapshot%20and%20are%20not%20in%20your%20staging%20area.). I also have keyboard shortcuts that affect a specific directory (and all of its subdirectories): ⌥⇧D for the current file's directory, ⌥⇧. for shell's current directory, ⌥⇧C for the current working directory according to VSCode/VSCodium, ⌥⇧W for the [Workspace](https://code.visualstudio.com/docs/editor/workspaces#:~:text=A%20Visual%20Studio%20Code%20%22workspace%22%20is%20the%20collection%20of%20one%20or%20more%20folders%20that%20are%20opened%20in%20a%20VS%20Code%20window) directory.@exm-key displays the ⌥⇧F shortcut as an example of the VSCode/VSCodium shortcut syntax. This shortcut uses the [escape code](https://en.wikipedia.org/wiki/ANSI_escape_code#C0_control_codes) for the [return key](https://en.wikipedia.org/wiki/ANSI_escape_code#C0_control_codes:~:text=0x0D,Carriage%20Return) (`\u000D`) to run several `git` commands and [predefined variables](https://code.visualstudio.com/docs/editor/variables-reference#_predefined-variables) to insert the absolute (`${file}`) and relative (`${relativeFile}`) path to the currently open file.::: {#exm-key}``` {.json filename="keybindings.json"}{ "key": "shift+alt+f", "command": "workbench.action.terminal.sendSequence", "args": { "text": "git add ${file} && git commit -m \"M ${relativeFile}\" && git push\u000D" }, "when": "terminalIsOpen"}```:::If you want to set up similar shortcuts for yourself, take a look at [my keybindings.json](https://github.com/maptv/setup/blob/main/keybindings.json) in my `setup` repo on [GitHub](https://github.com/maptv/setup) and [GitLab](https://gitlab.com/maptv/setup). As you create keyboard shortcuts, please be mindful of [keybinding conflicts](https://code.visualstudio.com/docs/getstarted/keybindings#_detecting-keybinding-conflicts) that may arise.To set up a keyboard shortcut that runs a series of steps rather than a single line of shell code, I suggest you use the VSCode/VSCodium [Tasks](https://code.visualstudio.com/docs/editor/tasks) mechanism, a system designed to [automate](https://en.wikipedia.org/wiki/Build_automation#:~:text=Build%20automation%20is%20the%20process%20of%20automating%20the%20creation%20of%20a%20software%20build)[software build](https://en.wikipedia.org/wiki/Software_build#:~:text=In%20software%20development%2C%20a%20build%20is%20the%20process%20of%20converting%20source%20code%20files%20into%20standalone%20software%20artifact(s)%20that%20can%20be%20run%20on%20a%20computer%2C%20or%20the%20result%20of%20doing%20so.) tasks. The default keyboard shortcut to run all tasks in a [local](https://code.visualstudio.com/docs/editor/tasks#_global-tasks:~:text=Workspace%20or%20folder%20specific%20tasks%20are%20configured%20from%20the%20tasks.json%20file%20in%20the%20.vscode%20folder%20for%20a%20workspace.) or [global](https://code.visualstudio.com/docs/editor/tasks#_global-tasks)`task.json` file is ⌃⇧B on Linux/Windows or ⌘⇧B on Mac (mnemonic: B is for Build), but you can [bind other shortcuts to specific tasks](https://code.visualstudio.com/docs/editor/tasks#_binding-keyboard-shortcuts-to-tasks).If you use a text editor like [Vim](https://en.wikipedia.org/wiki/Vim_(text_editor)#:~:text=Vim%20(/v%C9%AAm/%3B%5B5%5D%20a%20contraction%20of%20Vi%20IMproved)%20is%20a%20free%20and%20open%2Dsource%2C%20screen%2Dbased%20text%20editor%20program.) or [Emacs](https://en.wikipedia.org/wiki/Emacs#:~:text=Emacs%20/%CB%88i%CB%90m%C3%A6ks/%2C%20originally%20named%20EMACS%20(an%20acronym%20for%20%22Editor%20Macros%22)%2C%5B1%5D%5B2%5D%5B3%5D%20is%20a%20family%20of%20text%20editors%20that%20are%20characterized%20by%20their%20extensibility.), you can create keybindings for Vim plugins like [fugitive](https://github.com/tpope/vim-fugitive) or Emacs packages like [magit](https://magit.vc/) that run through the entire Git workflow. @exm-vim shows the Vim+fugitive equivalent of my ⌥⇧F VSCode/VSCodium keybinding.::: {#exm-vim}```sh {filename=".vimrc"}nnoremap <A-S-f> :Gw<bar>G! commit -m "M "%<bar>G! push<CR>```:::The drawback of my keyboard shortcut approach for the Git workflow is that it produces generic commit messages that are no very informative. Anyone reading the messages will not be able to tell what changes were made and more importantly why the changes were made.To automatically generate commit messages based on the currently staged changes, we can use a [Large Language Model](https://en.wikipedia.org/wiki/Large_language_model#:~:text=A%20large%20language%20model%20(LLM)%20is%20a%20type%20of%20language%20model%20notable%20for%20its%20ability%20to%20achieve%20general%2Dpurpose%20language%20understanding%20and%20generation.) (LLM). [Generative artificial intelligence](https://en.wikipedia.org/wiki/Generative_artificial_intelligence#:~:text=Generative%20artificial%20intelligence%20(also%20generative%20AI%20or%20GenAI%5B1%5D)%20is%20artificial%20intelligence%20capable%20of%20generating%20text%2C%20images%2C%20or%20other%20media) models like LLMs tend to be large in size and have atypical computational requirements, so I will save my adventures with LLMs for a [different post](../llm).I really enjoy using Git, especially with shell aliases in my terminal and keyboard shortcuts in my favorite text editors. If we ever collaborate on a project together, you can be sure that I will insist on using Git!