作为git reset
查询的一部分,我试图在每次提交时运行git index-filter
:
$ git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- *.xml' --prune-empty -- --all
但是,由于git reset
在单引号内,因此*
不会受到Bash的shell干扰;而是由git的pathspec规则处理。
这无法正常工作,因为我找不到告诉git reset
仅重置存储库根目录中文件的方法。
请考虑以下示例git repo:
.git/
a.xml
q.xml
directory1/b.xml
directory2/directory3/filename.txt
所需:只有a.xml
和q.xml
应该被重置
已观察到:a.xml
,q.xml
和directory1/b.xml
正在全部被重置。
我尝试了以下操作:
git reset '/*.xml'
-之所以失败,是因为它试图针对目录git reset
/
(显然不在我的git仓库中)git reset './*.xml'
-令人惊讶的是,这也重置了b.xml
git reset '$(find * -type f -maxdepth 1)'
-$()
无法识别git reset
,当然git不会将其传递给Bash进行处理,因此失败并显示一条错误消息git reset a.xml q.xml
-可以正常工作,好,但是,假设这些是我的所有以前的版本中存储库根目录中仅有的两个XML文件专案(视index-filter
正在针对每个先前的修订版本执行)。因此它可以正常工作,但是正确地。那么,有没有有效的git reset
路径规范可以在这里实际使用?
或者,我可以重写命令以避免使用单引号,以便Bash可以解释glob吗? (可以肯定这是不合适的,因为它仅适用于最新版本的存储库中的当前文件,而不适用于过去状态中存在的文件。)
也许我应该从单引号内调用bash
?
答案 0 :(得分:0)
正如您所指出的,*
不会在引号下扩展,您只需要将其移出引号即可。或者是使用数组并放入全局结果并将其传递给命令的更好方法。
shopt -s nullglob
xmlFiles=(*.xml)
默认情况下,*.xml
不会进行递归遍历,因此需要设置一个特殊选项,即globstar
来实现。不过,对于您自己的情况,您只能确认当前文件夹下的.xml
个文件,这些文件可能已经遍历了
echo '*.xml expands to '"${xmlFiles[@]}"''
因此,现在在git
命令中使用数组。
git filter-branch --index-filter \
'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- '"${xmlFiles[@]}"'' --prune-empty -- --all