Reputation: 5825
I am trying to write a Makefile
target that checks for no uncomitted changes in the git repository where it is ran after running another target.
This is what I have so far:
check-git-clean: other-target
ifneq ($(shell git diff-index --quiet HEAD; echo $$?), 0)
$(error "There are uncomitted changes after running make other-target")
endif
However, what I am experiencing is that if the other-target
causes uncommitted changes, the ifneq
will not catch it. On the other hand, if there were already uncommitted changes before I run make check-git-clean
, then the ifneq
does catch it.
So, in a way, it's almost as if the ifneq
is running "before" the make other-target
but the CLI output (echo) I get are in the right order.
I'm wondering how I can do this right.
Upvotes: 1
Views: 2247
Reputation: 2090
If you want the condition to be executed when the rule is executed rather than when the makefile is parsed, you need to use the if
function.
# This function tests whether both arguments are equals
equals = $(and $(findstring $1,$2),$(findstring $2,$1))
check-git-clean: other-target
$(if $(call equals,0,$(shell git diff-index --quiet HEAD; echo $$?)),, \
$(error There are uncomitted changes after running make $?) \
)
However, you may prefer to use a more natural approach to error out:
check-git-clean: other-target
git diff-index --quiet HEAD
Upvotes: 3
Reputation: 60295
In libexec/git-core there's a git-sh-setup
set of common utility routines for git commands and hooks, including require_clean_worktree
. The meat of that is
git update-index -q --ignore-submodules --refresh
git diff-files --quiet --ignore-submodules
git diff-index --cached --quiet --ignore-submodules HEAD --
where the index refresh is a safety play to deal with the chance you've just finished restoring your worktree from a backup or something, diff-files compares indexed content against worktree content and diff-index compares arbitrary repo content against indexed (in this case, because of --cached
) content. The return codes on those last two commands are what you're after.
Upvotes: 1
Reputation: 94502
May I recommend to use git diff --exit-code
directly?
.PHONY: check-git-clean
check-git-clean: other-target
git diff --quiet
or
.PHONY: check-git-clean
check-git-clean: other-target
git diff-index --quiet HEAD
Upvotes: 6