简体   繁体   中英

How to `git reset` non-recursively with git's pathspec globbing?

I'm trying to run a git reset on each commit, as part of a git index-filter query:

$ git filter-branch --index-filter 'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- *.xml' --prune-empty -- --all

However, because the git reset is within single quotes, the * is not subjected to Bash's shell globbing; it's being handled by git's pathspec rules instead.

This isn't working well because I can't find a way to tell git reset to only reset the files in the repository root.

Consider the following sample git repo:

.git/
a.xml
q.xml
directory1/b.xml
directory2/directory3/filename.txt

Desired: only a.xml and q.xml should be reset

Observed: a.xml , q.xml , and directory1/b.xml are all getting reset.

I've tried the following:

  • git reset '/*.xml' -- this fails because it's trying to git reset against the directory / , which obviously isn't inside my git repository
  • git reset './*.xml' -- surprisingly, this resets b.xml as well
  • git reset '$(find * -type f -maxdepth 1)' -- the $() is not recognised by git reset , and of course git doesn't pass it to Bash to handle it, so this fails with an error message
  • git reset a.xml q.xml -- this works okay , but, it assumes that those are the only two XML files in the repository root across all past revisions of my project (seeing as index-filter is running against every past revision). So it sort-of works, but not correctly .

So, is there a valid git reset pathspec that will actually work here?

Alternatively, can I rewrite my command to avoid the single quotes, so that Bash can interpret the globs? (Pretty sure this would be inappropriate because it'd only be applying against the current files in the latest revision of the repo, not the ones that existed in past states.)

Maybe I should literally be invoking bash from inside the single quotes?

As you've pointed out * doesn't expand under quotes and you just have to move it out of the quotes. Or a better way to use the array and put the glob results and pass it to the command.

shopt -s nullglob
xmlFiles=(*.xml)

By default *.xml does not undergo recursive globbing, one needs to set a special option ie globstar to achieve that. For your case though, you can confirm only the .xml files under the current folder which would have been globbed

echo '*.xml expands to '"${xmlFiles[@]}"''

So now using the array in your git command.

git filter-branch --index-filter \
     'git rm --cached -qr --ignore-unmatch -- . && git reset -q $GIT_COMMIT -- '"${xmlFiles[@]}"'' --prune-empty -- --all

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM