如何在忽略 .gitignore 的同时排除 Git 中的文件?
How to exclude files in Git while disregarding .gitignore?
背景
我正在将 VCS 迁移到 git。这是通过从旧 VCS (TFSVC) 检出并通过脚本检入 git 存储库来完成的。
本质上就是这样一个循环:
for x in $(seq 1 100)
do
tf get $x # get version x
git add . # add everything to index
git commit # commit
done
问题
旧版 VCS 包含 .gitignore
,作为迁移过程的一部分,我不希望应用这些模式。这可以使用 git add . --force
轻松解决。问题是还有一些我可能想忽略的东西。
我试过的
我本来希望使用 .git/info/exclude
作为目的,但是 git-add --force
除了 .gitignore
规则外显然忽略了这一点。 core.excludesFile
.
似乎也是如此
理想方案
- 排除
.gitignore
的规则
- 使用
.git/info/exclude
或其他一些排除文件或模式中的规则
- 有点性能,这个过程已经够慢了
- 不依赖于修改工作树
一个选项当然是在将所有内容添加到索引后简单地git restore --staged $EXCLUDE_PATH_SPEC
,但我想知道是否没有更好的解决方案。
我似乎记得看到过一个用于指定 ignore/exclude glob 的选项,但我似乎无法找到它。
也许有一种方法可以使用管道命令来实现此目的,例如 git update-index
?
编辑
我已添加说明,我宁愿不依赖修改工作树的解决方案(即:moving/modifying .gitignore
),因为它已被多次建议。主要是因为这些原因:
- 有嵌套
.gitignore
个文件
- 它们的存在和内容依赖于其他VCS的状态,我想完全控制
- 有另一个 VCS 跟踪文件,因此除了从其他 VCS 增量获取之外,任何修改工作树的事情都会使事情复杂化
- 它很可能更慢(尽管可能还不够慢,不足以成为主要问题)
如果你想忽略 git 中的几个文件,你可以执行以下命令-
git rm -r --cached .
git add .
git commit -m ".gitignore is now working"
到目前为止,我想出的最佳解决方案可能是使用 xargs
和 :!
排除路径。
grep --invert-match '^#' < .git/info/exclude |\
sed 's/^/:!/' |\
xargs git add --all --force --
对于我的用例来说,它可能工作得很好,但我不确定它是否是最佳解决方案。我不知道它如何处理复杂的规则,什么时候 xargs
会爆炸 git add
等。希望其他人能提出更好的答案。
临时删除.gitignore
怎么样?
for x in $(seq 1 100)
do
tf get $x
mv .gitignore /tmp/
git add .
mv /tmp/.gitignore .
git add .gitignore
git commit -m commit$x
done
如果标准便利不是您想要的,请使用核心命令创建您自己的便利。 git ls-files
可让您随心所欲地构建排除对象,git update-index
会随心所欲。
git ls-files -ocX /path/to/my/excludes \
| git update-index --add --remove --stdin
git ls-files
-o --others
在输出中显示其他(即未跟踪的)文件
-c --cached
在输出中显示缓存文件
-X --exclude-from
从中读取排除模式,每行 1 个。
git update-index
背景
我正在将 VCS 迁移到 git。这是通过从旧 VCS (TFSVC) 检出并通过脚本检入 git 存储库来完成的。
本质上就是这样一个循环:
for x in $(seq 1 100)
do
tf get $x # get version x
git add . # add everything to index
git commit # commit
done
问题
旧版 VCS 包含 .gitignore
,作为迁移过程的一部分,我不希望应用这些模式。这可以使用 git add . --force
轻松解决。问题是还有一些我可能想忽略的东西。
我试过的
我本来希望使用 .git/info/exclude
作为目的,但是 git-add --force
除了 .gitignore
规则外显然忽略了这一点。 core.excludesFile
.
理想方案
- 排除
.gitignore
的规则
- 使用
.git/info/exclude
或其他一些排除文件或模式中的规则 - 有点性能,这个过程已经够慢了
- 不依赖于修改工作树
一个选项当然是在将所有内容添加到索引后简单地git restore --staged $EXCLUDE_PATH_SPEC
,但我想知道是否没有更好的解决方案。
我似乎记得看到过一个用于指定 ignore/exclude glob 的选项,但我似乎无法找到它。
也许有一种方法可以使用管道命令来实现此目的,例如 git update-index
?
编辑
我已添加说明,我宁愿不依赖修改工作树的解决方案(即:moving/modifying .gitignore
),因为它已被多次建议。主要是因为这些原因:
- 有嵌套
.gitignore
个文件 - 它们的存在和内容依赖于其他VCS的状态,我想完全控制
- 有另一个 VCS 跟踪文件,因此除了从其他 VCS 增量获取之外,任何修改工作树的事情都会使事情复杂化
- 它很可能更慢(尽管可能还不够慢,不足以成为主要问题)
如果你想忽略 git 中的几个文件,你可以执行以下命令-
git rm -r --cached .
git add .
git commit -m ".gitignore is now working"
到目前为止,我想出的最佳解决方案可能是使用 xargs
和 :!
排除路径。
grep --invert-match '^#' < .git/info/exclude |\
sed 's/^/:!/' |\
xargs git add --all --force --
对于我的用例来说,它可能工作得很好,但我不确定它是否是最佳解决方案。我不知道它如何处理复杂的规则,什么时候 xargs
会爆炸 git add
等。希望其他人能提出更好的答案。
临时删除.gitignore
怎么样?
for x in $(seq 1 100)
do
tf get $x
mv .gitignore /tmp/
git add .
mv /tmp/.gitignore .
git add .gitignore
git commit -m commit$x
done
如果标准便利不是您想要的,请使用核心命令创建您自己的便利。 git ls-files
可让您随心所欲地构建排除对象,git update-index
会随心所欲。
git ls-files -ocX /path/to/my/excludes \
| git update-index --add --remove --stdin
git ls-files
-o --others
在输出中显示其他(即未跟踪的)文件-c --cached
在输出中显示缓存文件-X --exclude-from
从中读取排除模式,每行 1 个。
git update-index