Today a quick hack for pushing website updates.
For this Quarto website, I basically have my _quarto.yml
set up such that rendering my .qmd
documents to HTML will store the HTML files in a specific directory. In this case, the directory is _site
.
I then have a bash script that will push the files in this folder only to the repository that hosts the website, and push all source files to my public website code repository. This is fairly convenient since I just run the script to update the website. However, as my website started to have more and more pages, I realized that using quarto render
indiscriminately really slows down the process.
So it dawned upon me the other day that I could simply only render the files that have changed. Conveniently, git already tracks file changes, meaning I could use some git commands to figure out which files to render.
This was surprisingly easy to achieve. Here’s the essential part:
# Get list of changed .qmd or .md files in git working tree
CHANGED_FILES=$(git status --porcelain --untracked-files=no | awk '{print $2}' | grep -E '\.qmd$|\.md$')
if [ -z "$CHANGED_FILES" ]; then
echo "No changed Quarto files to render"
exit 0
fi
echo "Rendering changed files:"
echo "$CHANGED_FILES"
# Render changed files
quarto render $CHANGED_FILES
The first line simply generates a machine-readable list of changed .qmd
(and .md
) files in the git working tree. Then there’s an if clause and some print statements. Finally, identified files are rendered. Dead simple!
This is super convenient and speeds up the process of updating my website by a factor of 100 or so.
In case you’re interested, here’s the full bash script I use (at the time of writing):
#!/bin/bash
git add .
# Get list of changed .qmd or .md files in git working tree
CHANGED_FILES=$(git status --porcelain --untracked-files=no | awk '{print $2}' | grep -E '\.qmd$|\.md$')
if [ -z "$CHANGED_FILES" ]; then
echo "No changed Quarto files to render"
exit 0
fi
echo "Rendering changed files:"
echo "$CHANGED_FILES"
# Render changed files
quarto render $CHANGED_FILES
# Prompt for a commit message
echo "Enter a commit message:"
read commit_message
# --- Push source files to the main repository (lukmayer/website.git) ---
# Ensure the current directory is your main project directory (not _site)
# Add and commit changes to the source repo
git commit -m "$commit_message"
git remote add origin git@github.com:lukmayer/website.git
# Push changes to the main repository (lukmayer/website.git)
# Ensure 'origin' points to the source repo (lukmayer/website.git)
git push -f origin master
# --- Push rendered files to the GitHub Pages repository (lukmayer.github.io.git) ---
# Navigate to the _site directory (contains the rendered files)
cd _site
# Initialize a new Git repository inside _site if it doesn't exist already
if [ ! -d ".git" ]; then
git init
git remote add origin git@github.com:lukmayer/lukmayer.github.io.git
else
git remote set-url origin git@github.com:lukmayer/lukmayer.github.io.git
fi
# Add and commit the rendered site files
git add .
git commit -m "$commit_message"
# Force push the rendered files to the gh-pages branch of the GitHub Pages repo
git push -f origin master:gh-pages # Ensure that 'gh-pages' is the correct branch for GitHub Pages
# Navigate back to the root directory of the project
cd ..
If you use this script, make sure to give it execute permissions with chmod +x update.sh
1 and run it with ./update.sh
. Enjoy! :)
1 Always make sure you know what shell commands do before doing this!