Even more Web-based editors can even run code and build software if equipped with computational resources via a service such as GitHub Codespaces and GitPod. have free tiers that should be sufficient for most . in cloud-based environments, which facilitates reproducibility. Notably,
Like vscode.dev, these web-based editors provide access to the Visual Studio Code (VSCode) source-code editor via a web browser, but distinguish themselves from editors that instead of the local file system. from other services that such as by
If you do not have such a repo, you can create one by following along with the previous post in my tools blog post series, which is shown in Figure 1.
If you are not completely satisfied with the integrated terminal built into your preferred source-code editor or the standalone terminal that comes with your operating system (OS), you can use Homebrew to install a new one. The standalone terminal I use most often is iTerm2, which is only for macOS, but I also have the following multi-OS terminals: 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.
If you are curious about how I set up my computer, you can take a look at my Brewfile and other configuration files in my setup repo on GitHub and GitLab. I will highlight a few configuration files in Section 4.
Codespaces
As an alternative to installing tools on your computer, you can use GitHub Codespaces to perform all development tasks remotely. To get a feel for Codespaces, I recommend you first try the github.dev editor.
Both Codespaces and github.dev allow you to edit files in any GitHub repository via VSCode in your browser and load your VSCode settings automatically via Settings Sync, but github.dev can be started by going to any repo on GitHub and pressing . or changing the .com in the URL to .dev, e.g.https://github.com/maptv/maptv.github.io to https://github.dev/maptv/maptv.github.io. The github.dev editor starts up fast and is completely free, but comes with restrictions that prevent us from running code, building software, accessing the integrated terminal, or using non-web extensions.
In addition to being free of these restrictions, Codespaces allows us to use JupyterLab as the web interface instead of VSCode by appending /?editor=jupyter to the Codespaces URL. If you use a JetBrainsintegrated development environmentproducts, such as PyCharm (IDE), you can also try appending /?editor=jetbrains to the Codespaces URL and accessing Codespaces via JetBrains Gateway.
Every Codespaces instance (codespace) is pre-equipped with commonly used tools. If you want your codespaces to start with additional tools or settings for any tools other than VSCode, you will need to create a repo called dotfiles and enable automatic installation of your configuration files into every codespace you create.
“Dotfiles” is a general term for files that contain user settings. The term “dotfiles” is derived from hidden files in Unix and Unix-like environments, which have names that start with a dot (.). Despite the origin of the term, not all dotfiles are hidden files.
In fact, there is a new convention that places non-hidden configuration files in a hidden directory called .config. Despite the growing popularity of this new convention, many dotfiles are still stored according to the old convention, i.e. as hidden files in the home directory.
Example 3 shows how the Vim and Neovimtext editors differ in their approach to dotfile storage. The Vim configuration file ~/.vimrc follows the old convention, while the Neovim configuration file (~/.config/nvim/init.vim) follows the new convention, where ~ represents the home directory and / is directory delimiter used in Unix paths.
If do not have configuration files for any tool other than VSCode and do not need to install anything as part of Codespaces setup, you can forego creating a dotfiles repo and simply enable Settings Sync.
you can simply include all of your configuration files in your dotfiles repo with the desired directory structure, e.g. as in Example 3. This way, whenever a codespace is created, its home directory (/home/codespace) will be set up to match your dotfiles repo using symbolic links.
While this automatic dotfile setup approach does not allow you to install any additional tools, it is simple and avoids any installation steps that can significantly slow down build times. Importantly, if GitHub determines that your dotfiles repo contains a setup script based on its naming convention, it will not run the setup script and ignore any other files in the repo, because of the expectation that users with setup scripts will want to organize their configuration files themselves.
For more information on dotfiles, check out the resources at https://dotfiles.github.io. Regardless o you do have way to configure VSCode, you do not have to set up Codespaces. Instead you can any of the steps below https://docs.github.com/en/codespaces/setting-your-user-preferences/personalizing-github-codespaces-for-your-account#settings-sync
The setup script can install
Regardless of whether you have a dotfiles repo, you can use Settings Sync to maintain consistency between your local and remote development environments. keep all of your configuration files in a repo called dotfiles. Instead
but we can add anything that may be missing with a Brewfile and a setup script.
In other words, we have the option to simply put configuration files in our dotfiles repo and not install anything.
My configuration files have dependencies that are not included in the default Codespaces image, so the configuration-files-only approach would not work for me. Codespaces of the expectation
I chose setup.sh as the name of my setup script because it was shortest name that followed the naming convention set by GitHub and had the .shfilename extension.
For my configurationI need at very least convenient feature is disabled when we include a setup script in our dotfiles repo, because
The tools listed in the Brewfile can be installed with a shell script that GitHub will run when building the Codespace.
It is essential that your setup script be added to Git as an executable script! I only needed to run the shell code in Example 4 once for Git to change the mode of setup.sh and remember forever that its access permissions include execution (x).
Example 4
git add setup.sh --chmod=+x
Maintaining local and remote settings may be challenging, but Homebrew makes it easier with the $HOMEBREW_PREFIX environment variable. This variable contains the Homebrew installation path that matches your computer hardware and OS.
Before you can use $HOMEBREW_PREFIX, the brew command needs to be added to your PATH. To ensure Codespaces setup, I added the code in Example 5 to my .zshrc.
To prevent conflicts with web browser keybindings, you can install Codespaces as a Progressive Web App (PWA) by clicking on the “Install Codespaces” icon at the end of the URL bar in Chrome or any Chromium-based web browser. When running as a PWA, Codespaces behaves like a desktop application and can thus provide a familiar user experience on any computer!
On macOS, the PWA installation location is ~/Applications/Chrome Apps.localized.
Repository
Before you can benefit from everything GitHub and GitLab have to offer, you will need a GitHub and/or GitLab account and an SSH key. Even though there are other authentication methods, SSH keys are still the easiest way to authenticate to GitHub and GitLab.
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 4.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: Positrondraft: trueauthor: - name: Martin Laptev url: https://maptv.github.iodate: last-modifiedimage: vscodium.pngcategories: - tool - git - vscodedate-format: xformat: html: include-after-body: - ../../asset/stamp.html - ../../asset/style.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"}The goal of this blog post, the second in the [Tools](..#category=tool) blog post series summarized by @fig-navchart, is to set up the [Visual Studio Code](https://code.visualstudio.com) (VSCode) [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.) to run in the remote development environments provided by 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.). To accomplish this goal, we will use VSCode to edit a setup [script](https://en.wikipedia.org/wiki/Shell_script#:~:text=A%20shell%20script%20is%20a%20computer%20program%20designed%20to%20be%20run%20by%20a%20Unix%20shell%2C%20a%20command%2Dline%20interpreter.%5B) and configuration files in 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) named `dotfiles`.```{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 "../knitr" click F "../jupyter" style B stroke:#99f,stroke-width:5px```## Introduction {#sec-intro}Even more Web-based editors can even run code and build software if equipped with computational resources via a service such as [GitHub Codespaces](https://github.com/features/codespaces) and [GitPod](https://www.gitpod.io). have free tiers that should be sufficient for most . in [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 environments, which facilitates [reproducibility](https://en.wikipedia.org/wiki/Reproducibility#:~:text=reproducibility%20has%20been%20introduced%20in%20computational%20sciences%3A%20Any%20results%20should%20be%20documented%20by%20making%20all%20data%20and%20code%20available%20in%20such%20a%20way%20that%20the%20computations%20can%20be%20executed%20again%20with%20identical%20results.). Notably, Like [vscode.dev](https://vscode.dev), these web-based editors provide access to the [Visual Studio Code](https://code.visualstudio.com) (VSCode) [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.) 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), but distinguish themselves from editors that instead of the local file system. from other services that such as by If you do not have such a repo, you can create one by following along with the [previous post](../git) in my [tools](..#category=tool) blog post series, which is shown in @fig-navchart.## 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 use Homebrew to install everything needed to follow along with this blog post. First, [install Homebrew](https://brew.sh/#install) 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.github\usercontent.com/Homebrew/install/HEAD/install.sh)"```:::If you are not completely satisfied with the integrated terminal built into your 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.) or the standalone 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 one. The standalone terminal I use most often is [iTerm2](https://formulae.brew.sh/cask/iterm2#default), which is only for macOS, but I also have the following multi-OS terminals: [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"\nbrew "glab"cask "github"\ncask "rstudio"\ncask "vscodium"cask "visual-studio-code"' > 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/),- 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), and- three source-code editors: - [Visual Studio Code (VSCode)](https://code.visualstudio.com), - [VSCodium](https://vscodium.com/#:~:text=VSCodium%20is%20a%20community%2Ddriven%2C%20freely%2Dlicensed%20binary%20distribution%20of%20Microsoft%E2%80%99s%20editor%20VS%20Code.), and - [RStudio](https://posit.co/download/rstudio-desktop).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) and other configuration files in my `setup` repo on [GitHub](https://github.com/maptv/setup) and [GitLab](https://gitlab.com/maptv/setup). I will highlight a few configuration files in @sec-workflow.### Codespaces {#sec-setup-code}As an alternative to installing tools on your computer, you can use [GitHub Codespaces](https://github.com/features/codespaces) to perform all development tasks remotely. To get a feel for Codespaces, I recommend you first try the [`github.dev` editor](https://docs.github.com/en/codespaces/the-githubdev-web-based-editor).Both Codespaces and `github.dev` allow you to edit files in any GitHub repository via VSCode in your browser and load your VSCode settings automatically via [Settings Sync](https://docs.github.com/en/codespaces/setting-your-user-preferences/personalizing-github-codespaces-for-your-account#settings-sync), but `github.dev` can be started by going to any repo on GitHub and pressing `.` or changing the `.com` in the [URL](https://en.wikipedia.org/wiki/URL#:~:text=A%20Uniform%20Resource%20Locator%20(URL)%2C%20colloquially%20known%20as%20an%20address%20on%20the%20Web) to `.dev`, [e.g.](https://en.wikipedia.org/wiki/List_of_Latin_phrases_(E)#exempli_gratia) <https://github.com/maptv/maptv.github.io> to <https://github.dev/maptv/maptv.github.io>. The `github.dev` editor starts up fast and is completely free, but comes with restrictions that prevent us from running code, building software, accessing the [integrated terminal](https://code.visualstudio.com/docs/terminal/basics), or using [non-web extensions](https://docs.github.com/en/codespaces/the-githubdev-web-based-editor#using-extensions:~:text=The%20github.dev%20editor%20supports%20VS%20Code%20extensions%20that%20have%20been%20specifically%20created%20or%20updated%20to%20run%20in%20the%20web.).In addition to being free of these restrictions, Codespaces allows us to use JupyterLab as the web interface instead of VSCode by appending `/?editor=jupyter` to the Codespaces URL. If you use a [JetBrains](https://www.jetbrains.com)[integrated development environment](https://en.wikipedia.org/wiki/Integrated_development_environment#:~:text=An%20integrated%20development%20environment%20(IDE)%20is%20a%20software%20application%20that%20provides%20comprehensive%20facilities%20for%20software%20development.)products, such as [PyCharm](https://www.jetbrains.com/pycharm) (IDE), you can also try appending `/?editor=jetbrains` to the Codespaces URL and accessing Codespaces via [JetBrains Gateway](https://www.jetbrains.com/remote-development/gateway).Every Codespaces instance ([codespace](https://docs.github.com/en/codespaces/overview#:~:text=A%20codespace%20is%20a%20development%20environment%20that%27s%20hosted%20in%20the%20cloud.)) is pre-equipped with commonly used tools. If you want your codespaces to start with additional tools or settings for any tools other than VSCode, you will need to create a repo called [`dotfiles`](https://docs.github.com/en/codespaces/customizing-your-codespace/personalizing-github-codespaces-for-your-account#dotfiles) and [enable automatic installation](https://docs.github.com/en/codespaces/setting-your-user-preferences/personalizing-github-codespaces-for-your-account#enabling-your-dotfiles-repository-for-codespaces) of your configuration files into every codespace you create.["Dotfiles"](https://en.wiktionary.org/wiki/dotfile#:~:text=A%20file%20or%20directory%20whose%20name%20begins%20with%20a%20dot%20(period%20or%20full%20stop)%2C%20typically%20hidden%20from%20view%20and%20sometimes%20used%20to%20store%20configuration%20settings.) is a general term for files that contain [user settings](https://en.wikipedia.org/wiki/Hidden_file_and_hidden_directory#Unix_and_Unix-like_environments:~:text=A%20convention%20arose%20of%20using%20dotfiles%20in%20the%20user%27s%20home%20directory%20to%20store%20per%2Duser%20configuration). The term "dotfiles" is derived from [hidden files](https://en.wikipedia.org/wiki/Hidden_file_and_hidden_directory#Unix_and_Unix-like_environments) in Unix and Unix-like environments, which have names that start with a dot (`.`). Despite the origin of the term, not all dotfiles are hidden files.In fact, there is a [new convention](https://en.wikipedia.org/wiki/Hidden_file_and_hidden_directory#Unix_and_Unix-like_environments:~:text=the%20Unix/Linux%20freedesktop.org%20XDG%20Base%20Directory%20Specification%20aims%20to%20migrate%20user%20config%20files%20from%20individual%20dotfiles%20in%20%24HOME%20to%20non%2Dhidden%20files%20in%20the%20hidden%20directory%20%24HOME/.config.) that places non-hidden configuration files in a hidden directory called `.config`. Despite the growing popularity of this new convention, many dotfiles are still stored according to the old convention, [i.e.](https://en.wikipedia.org/wiki/List_of_Latin_phrases_(I)#id_est) as hidden files in 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.).@exm-tree shows how the [Vim](https://en.wikipedia.org/wiki/Vim_(text_editor)#Neovim:~: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.) and [Neovim](https://en.wikipedia.org/wiki/Vim_(text_editor)#Neovim:~:text=Neovim%5B62%5D%20is%20a%20fork%20of%20Vim%20that%20strives%20to%20improve%20the%20extensibility%20and%20maintainability%20of%20Vim.) [text editors](https://en.wikipedia.org/wiki/Text_editor#:~:text=A%20text%20editor%20is%20a%20type%20of%20computer%20program%20that%20edits%20plain%20text.) differ in their approach to dotfile storage. The Vim configuration file `~/.vimrc` follows the old convention, while the Neovim configuration file (`~/.config/nvim/init.vim`) follows the new convention, 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 and `/` is [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 [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.).::: {#exm-tree}```~├── .config│ └── nvim│ └── init.vim└── .vimrc```:::If do not have configuration files for any tool other than VSCode and do not need to install anything as part of Codespaces setup, you can forego creating a `dotfiles` repo and simply enable Settings Sync.you can simply include all of your configuration files in your `dotfiles` repo with the desired directory structure, e.g. as in @exm-tree. This way, whenever a codespace is created, its home directory (`/home/codespace`) will be set up to match your `dotfiles` repo using [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link#:~:text=a%20symbolic%20link%20(also%20symlink%20or%20soft%20link)%20is%20a%20file%20whose%20purpose%20is%20to%20point%20to%20a%20file%20or%20directory%20(called%20the%20%22target%22)%20by%20specifying%20a%20path%20thereto.).While this automatic dotfile setup approach does not allow you to install any additional tools, it is simple and avoids any installation steps that can significantly slow down build times. Importantly, if GitHub determines that your `dotfiles` repo contains a setup script based on its [naming convention](https://docs.github.com/en/codespaces/setting-your-user-preferences/personalizing-github-codespaces-for-your-account#:~:text=install.sh,script/setup), it will not run the setup script and ignore any other files in the repo, because of the expectation that users with setup scripts will want to organize their configuration files themselves.For more information on dotfiles, check out the resources at <https://dotfiles.github.io>. Regardless o you do have way to configure VSCode, you do not have to set up Codespaces. Instead you can any of the steps belowhttps://docs.github.com/en/codespaces/setting-your-user-preferences/personalizing-github-codespaces-for-your-account#settings-syncThe setup script can install Regardless of whether you have a `dotfiles` repo, you can use [Settings Sync](https://docs.github.com/en/codespaces/setting-your-user-preferences/personalizing-github-codespaces-for-your-account#settings-sync) to maintain consistency between your local and remote development environments. keep all of your configuration files in a repo called [`dotfiles`](https://docs.github.com/en/codespaces/customizing-your-codespace/personalizing-github-codespaces-for-your-account#dotfiles). Instead but we can add anything that may be missing with a `Brewfile` and a setup [script](https://en.wikipedia.org/wiki/Shell_script#:~:text=A%20shell%20script%20is%20a%20computer%20program%20designed%20to%20be%20run%20by%20a%20Unix%20shell%2C%20a%20command%2Dline%20interpreter.%5B).In other words, we have the option to simply put configuration files in our `dotfiles` repo and not install anything.My configuration files have dependencies that are not included in the default Codespaces image, so the configuration-files-only approach would not work for me. Codespaces of the expectationI chose `setup.sh` as the name of [my setup script](https://github.com/maptv/dotfiles/blob/main/setup.sh) because it was shortest name that followed the naming convention set by GitHub and had the `.sh`[filename extension](https://en.wikipedia.org/wiki/Filename_extension#:~:text=A%20filename%20extension%2C%20file%20name%20extension%20or%20file%20extension%20is%20a%20suffix%20to%20the%20name%20of%20a%20computer%20file%20(for%20example%2C%20.txt%2C%20.docx%2C%20.md).).For my configurationI need at very least convenient feature is disabled when we include a setup script in our `dotfiles` repo, becauseThe tools listed in the `Brewfile` can be installed with a shell script that GitHub will run when building the Codespace.It is essential that your setup script be added to Git as an [executable](https://en.wikipedia.org/wiki/Executable#:~:text=In%20computing%2C,to%20be%20meaningful.) script! I only needed to run the shell code in @exm-set once for Git to [change the mode](https://en.wikipedia.org/wiki/Chmod#:~:text=chmod%20was%20chosen%20as%20an%20abbreviation%20of%20change%20mode.) of `setup.sh` and remember forever that its [access permissions](https://en.wikipedia.org/wiki/File-system_permissions) include execution (`x`).::: {#exm-set}``` shgit add setup.sh --chmod=+x```:::Maintaining local and remote settings may be challenging, but Homebrew makes it easier with the `$HOMEBREW_PREFIX` environment variable. This variable contains the Homebrew installation path that matches your [computer hardware and OS](https://docs.brew.sh/Installation#:~:text=/opt/homebrew%20for%20Apple%20Silicon%2C%20/usr/local%20for%20macOS%20Intel%20and%20/home/linuxbrew/.linuxbrew%20for%20Linux).Before you can use `$HOMEBREW_PREFIX`, the `brew` command needs to be added to your PATH. To ensure Codespaces setup, I added the code in @exm-path to my `.zshrc`.::: {#exm-path}``` {.sh filename=".zshrc"}if [[ "$(uname)" == 'Linux' ]]; then eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"fi```:::To prevent conflicts with [web browser](https://en.wikipedia.org/wiki/Web_browser#:~:text=A%20web%20browser%20is%20an%20application%20for%20accessing%20websites%20and%20the%20Internet.) keybindings, you can install Codespaces as a [Progressive Web App](https://code.visualstudio.com/docs/remote/codespaces#_known-limitations-and-adaptations) (PWA) by clicking on the "Install Codespaces" icon at the end of the [URL bar in Chrome](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Guides/Making_PWAs_installable#:~:text=a%20browser%20might%20include%20an%20%22Install%22%20icon%20in%20the%20URL%20bar%20when%20the%20user%20navigates%20to%20the%20page%3A) or any [Chromium](https://en.wikipedia.org/wiki/Chromium_(web_browser)#:~:text=Chromium%20is%20a%20free%20and%20open%2Dsource%20web%20browser%20project%2C%20primarily%20developed%20and%20maintained%20by%20Google.)-based web browser. When running as a PWA, Codespaces behaves like a desktop application and can thus provide a familiar user experience on any computer!On macOS, the PWA installation location is `~/Applications/Chrome Apps.localized`. ### Repository {#sec-setup-repo}Before you can benefit from everything GitHub and GitLab have to offer, you will need a [GitHub](https://github.com/signup) and/or [GitLab](https://gitlab.com/users/sign_up) account and an [SSH key](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). Even though there are other [authentication methods](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-authentication-to-github#about-authentication-to-github), SSH keys are still the easiest way to authenticate to GitHub and GitLab.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).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](../../ml/llm/index.qmd).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!