git merge crash "fatal: stash failed" with smudge/clean filters
- From
Joey Hess <id@joeyh.name>
- Date
- May 2, 2023, 17:21 UTC
- Message-ID
- <ZFFGi9i7JGL9xNx5@kitenet.net>
The attached testcase seems to show a bug in git. git merge crashes with an internal error of "fatal: stash failed".
The testcase uses some very basic smudge/clean filters, and that is necessary to see the crash. (The filters may be kinda broken, they're the first thing I tried to detangle this bug from git-annex.)
The test case first creates an empty file, and that is somehow significant. While the merge does not directly involve that empty file, omitting adding the empty file, or making it have any non-empty content avoids the merge crash. And the crash happens after cleaning the empty file:
joey@darkstar:~/tmp/x/testcase-workdir/repo1>GIT_PACKET_TRACE=1 GIT_TRACE=1 git merge repo2/master 13:17:20.064936 git.c:439 trace: built-in: git merge repo2/master 13:17:20.070120 run-command.c:655 trace: run_command: '.git/test-clean '\''emptyfile'\''' 13:17:20.094653 run-command.c:655 trace: run_command: git stash create 13:17:20.097780 git.c:439 trace: built-in: git stash create 13:17:20.099213 run-command.c:655 trace: run_command: '.git/test-clean '\''emptyfile'\''' fatal: stash failed
git version 2.40.1.459.g48d89b51b3
--
see shy jo
#!/bin/bash
setup_smudge_clean() {
cat <<'EOF' > .git/test-clean
#!/bin/sh
mkdir -p ../content
cat > ../content/new.content
v=$(sha1sum ../content/new.content | cut -d ' ' -f 1)
mv ../content/new.content ../content/$v.content
echo "$v"
EOF
cat <<'EOF' > .git/test-smudge
#!/bin/sh
v=$(cat)
cat ../content/$v.content
EOF
chmod +x .git/test-clean
chmod +x .git/test-smudge
git config filter.foo.smudge '.git/test-smudge %f'
git config filter.foo.clean '.git/test-clean %f'
echo "* filter=foo" > .git/info/attributes
}
mkdir testcase-workdir
cd testcase-workdir
git init repo1
cd repo1
setup_smudge_clean
git commit --allow-empty -m foo
git remote add repo2 ../repo2
cd ..
git clone repo1 repo2
cd repo2
git remote add repo1 ../repo1
setup_smudge_clean
cd ..
cd repo1
touch emptyfile
git add emptyfile
git commit -m add
cd ../repo2
git pull
echo foo > testfile
git add testfile
git commit -m foo
cd ../repo1
echo bar > testfile
git add testfile
git commit -m bar
git fetch repo2 master
git merge repo2/master # crashes