我有一個腳本可以更新儲存庫,並在某些給定路徑中新增/刪除檔案。知道路徑後如何提交這些變更? 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