リポジトリを更新し、特定のパスにファイルを追加および削除するスクリプトがあります。パスがわかったら、これらの変更をどのように適用しますか?つまり、
- 指定されたファイルが作業ツリーにある場合は、インデックスにコピーします。
- 指定されたファイルが索引にあるが作業ツリーにない場合は、索引から削除します。
- 指定されたファイルがジョブツリーまたはインデックスにない場合は、何も実行されません。
git add
最後のケースでは失敗します。コマンドラインにパスがないとエラーが発生し、何もしません。
私は以下を考慮しました。
git add --ignore-errors
、残念ながら、ファイルが存在しないことを無視するエラーの種類として扱われません。git add --ignore-missing
残念ながら存在するが--dry-run
。エラーを無視してパスごとに1回呼び出すと
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
または、1 回の通話で次の操作を行います。
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