Skip to content
shellhacks.dev
CI/CD

Check what changed in a pull request

List the files a pull request changed with git diff --name-only origin/main...HEAD. Three dots compare against the merge base, and a shallow checkout cannot do it.

2 min read
Summarize in AI

A CI job should run only when certain files changed, and the list of files must be those of the branch and not whatever landed on main since.

Shell
git init -q -b main origin && cd origin
echo 1 > base.txt && git add . && git commit -qm base
cd .. && git clone -q origin work && cd work
git checkout -q -b feature
echo 2 > feature.txt && git add . && git commit -qm feature
cd ../origin && echo 3 > main-only.txt && git add . && git commit -qm "main moves on"
cd ../work && git fetch -q origin
echo "two dots:";   git diff --name-only origin/main..HEAD
echo "three dots:"; git diff --name-only origin/main...HEAD
cd .. && git clone -q --depth 1 --branch feature "file://$PWD/work" shallow && cd shallow
git fetch -q --depth 1 origin main:refs/remotes/origin/main
git diff --name-only origin/main...HEAD
Text
two dots:
feature.txt
main-only.txt
three dots:
feature.txt
fatal: origin/main...HEAD: no merge base

Two dots compare the two tips, so main-only.txt shows up as if the branch had deleted it. Three dots compare the branch with the merge base, the point where it left main, and list only what the branch changed, which is what a path filter wants. The rule is in the git diff manual. The last command fails because a clone with depth 1 holds no history to find a merge base, so the CI checkout needs fetch-depth: 0 or a deeper fetch.

In a pull request workflow GitHub checks out a merge commit, where the first parent is the base branch, so comparing it with HEAD lists the changes of the pull request without needing the base ref. A rename shows as one path with --name-only unless --no-renames is added. Use -z for names that hold unusual characters.

Share

More snippets

CI/CD

Run a script from the repo

Run a repository script from a workflow with run: ./script.sh only if Git stores it as executable. Otherwise the step fails with Permission denied, status 126.

2 min read
CI/CD

Group log lines in GitHub Actions

Fold log output in GitHub Actions by printing ::group::Title and ::endgroup::. A wrapper function keeps the pair together and passes the command's status on.

1 min read
CI/CD

Print a warning annotation

Print ::warning file=...,line=...::message from a step to show an annotation on the run and in the pull request diff. Newlines in the text must be encoded.

1 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.