Thanks @Etan Resiner for your answer. Here's an example showing how to use the output of git diff --name-only -z "$merge_base" $BACKUP_BRANCH
as input to contain escaped filenames sent into git diff
or git difftool
. It requires an extra --
, so see the code below.
I was able to fix my git changes
program with it, so now it can handle filenames in a git repo which have spaces or special chars (such as '
) in the filenames. Now, the program looks like this:
Usage:
Usage: git changes <common_base> <backup_branch> [any other args to pass to git difftool]
git-changes.sh:
Notice especially the filling of the files_changed_escaped
variable, which was directly learned from @Etan Reisner's answer.
COMMON_BASE_BRANCH="$1"
BACKUP_BRANCH="$2"
# Obtain all but the first args; see:
# https://mcmap.net/q/63808/-process-all-arguments-except-the-first-one-in-a-bash-script/9057392#9057392
ARGS_3_AND_LATER="${@:3}"
merge_base="$(git merge-base $BACKUP_BRANCH $COMMON_BASE_BRANCH)"
files_changed="$(git diff --name-only "$merge_base" $BACKUP_BRANCH)"
echo "Checking for changes against backup branch \"$BACKUP_BRANCH\""
echo "only in these files which were previously-modified by that backup branch:"
echo "--- files originally changed by the backup branch: ---"
echo "$files_changed"
echo "------------------------------------------------------"
echo "Checking only these files for differences between your backup branch and your current branch."
# Now, escape the filenames so that they can be used even if they have spaces or special characters,
# such as single quotes (') in their filenames!
# See: https://mcmap.net/q/450141/-how-to-cope-with-spaces-in-file-names-when-iterating-results-from-git-diff-name-only/28109890#28109890
files_changed_escaped=""
while IFS= read -r -d '' file; do
escaped_filename="$(printf "%q" "$file")"
files_changed_escaped="${files_changed_escaped} ${escaped_filename}"
done < <(git diff --name-only -z "$merge_base" $BACKUP_BRANCH)
# DEBUG PRINTS. COMMENT OUT WHEN DONE DEBUGGING.
echo "$files_changed_escaped"
echo "----------"
# print withOUT quotes to see if that changes things; ans: indeed, it does: this removes extra
# spaces and I think will replace each true newline char (\n) with a single space as well
echo $files_changed_escaped
echo "=========="
# NB: the `--` is REQUIRED before listing all of the files to search in, or else escaped files
# that have a dash (-) in their filename confuse the `git diff` parser and the parser thinks they
# are options! It will output this error:
# fatal: option '-\' must come before non-option arguments
# Putting the list of all escaped filenames to check AFTER the `--` forces the parser to know
# they cannot be options, because the `--` with nothing after it signifies the end of all optional
# args.
git difftool $ARGS_3_AND_LATER $BACKUP_BRANCH -- $files_changed_escaped
echo "Done."
You can download the git changes
program as part of my dotfiles project here: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles.
It also contains such things as git diffn
, which is git diff
with line numbers.