如何使用git的pathspec遍历非递归地进行git reset?

时间:2018-12-04 05:27:12

标签: bash git glob

作为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.xmlq.xml应该被重置

已观察到:a.xmlq.xmldirectory1/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

1 个答案:

答案 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