我有一个脚本可以更新存储库,并在某些给定路径中添加/删除文件。知道路径后如何提交这些更改? IE,
- 如果指定文件在工作树中,则将其复制到索引
- 如果指定的文件在索引中但不在工作树中,则将其从索引中删除
- 如果指定的文件既不在工作树中也不在索引中,则不执行任何操作。
git add
在最后一个极端情况下失败 - 如果其命令行上的任何路径不存在,则会出现错误并不执行任何操作。
我考虑过:
git add --ignore-errors
,不幸的是,它不会将文件不存在视为它忽略的错误类型。git add --ignore-missing
令人沮丧地存在,但仅适用于--dry-run
.每个路径一次
git add
调用,忽略错误,可以工作,但速度很慢,并且不允许将由于文件不存在(既不在索引也不在工作树中)而导致的错误与其他错误区分开来。一次
git add --all
调用不允许仅在某些路径上暂存文件。
答案1
git add
到目前为止,我发现的最佳解决方案是通过显式检查 git 索引和工作树来构造要传递到的路径列表。
给定存储库:
git init .
echo $RANDOM > ignore-edited
echo $RANDOM > ignore-deleted
echo $RANDOM > add-edited
echo $RANDOM > add-deleted
git add .
git commit -m 'Initial commit'
echo $RANDOM > ignore-new
echo $RANDOM > ignore-edited
rm ignore-deleted
echo $RANDOM > add-new
echo $RANDOM > add-edited
rm add-deleted
以及要更新的文件列表:
printf '%s\n' add-new add-edited add-deleted add-nonexistent | sort \
> /tmp/filelist.txt
我们可以通过获取要添加的文件和索引的交集以及要添加的文件和工作树中现有文件的交集之间的并集来构造文件列表:
comm -12 /tmp/filelist.txt <(git ls-files) \
> /tmp/files-in-index.txt
while read -r line ; do test -e "$line" && printf -- '%s\n' "$line" ; done < /tmp/filelist.txt \
> /tmp/files-in-worktree.txt
sort -um /tmp/files-in-index.txt /tmp/files-in-worktree.txt \
> /tmp/files-to-add.txt
< /tmp/files-to-add.txt xargs git add
或者,在一次调用中:
sort -um \
<(comm -12 /tmp/filelist.txt <(git ls-files)) \
<(while read -r line ; do test -e "$line" && printf -- '%s\n' "$line" ; done < /tmp/filelist.txt) |
xargs git add