12

I've moved files from Project to Project/src. Git is under the impression that I've deleted the files from Project and created new files in Project/src.

In addition, I have multiple other changes in the working tree, which I wish to commit. My git status:


 $ git  status
# On branch feature/cmake
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#   new file:   .gitignore
#   new file:   CMakeLists.txt
#   deleted:    Wasa.xcodeproj/project.pbxproj
#   deleted:    Wasa/Wasa.1
#   renamed:    Wasa/main.cpp -> main.cpp
#   new file:   src/CMakeLists.txt  
#  Lots of new files listed here
#
# Changes not staged for commit:
#   (use "git add/rm ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#   modified:   CMakeLists.txt
#   deleted:    IODevice.h
#  Lots of deleted files listed here.

I'd like to unstage the source files - *.{cpp,h}. I know how to unstage (the link here, for example, is helpful). What I'd like to avoid doing is typing lots of git checkout <filename>.

I don't want to checkout HEAD, because some of the changes in the working tree I'd like to keep. I've tried doing git checkout *.{cpp,h}, which gives the following:


$ git checkout *.{cpp,h}
zsh: no matches found: *.cpp

Because the files don't currently exist in the working tree, I can't check them out because *.{cpp,h} doesn't match any files.

The files are all in Project/src; there is probably a regex or something I could run with the output of ls src piped into the git checkout command, but I'd like to know if git can do this for me by itself. Is there a way I can do this in git?

Community
  • 1
  • 1
simont
  • 68,704
  • 18
  • 117
  • 136

2 Answers2

28

Escape the *:

$ git checkout \*.{cpp,h}
Irfy
  • 9,323
  • 1
  • 45
  • 67
  • If the files exist in the directory, git (or maybe the shell, I'm not sure which) accepts the `*.{cpp,h}` and expands it to all matching files. My issue is that I don't *have* matching files; they've moved to `src/*.{cpp,h}` and I'm trying to find a lazy way to checkout the files without typing `git checkout `, `git checkout ` etc. – simont Feb 19 '12 at 01:56
  • If you escape the star, it won't match in the shell. Just try it :-) – Irfy Feb 19 '12 at 01:58
  • Heh. My bad; completely mis-read what you'd written. That works - thank you very much. – simont Feb 19 '12 at 02:07
  • Sorry for being a noob but the complete command would help. Thanks – pal4life Jul 29 '14 at 20:03
  • 2
    `$ git checkout \*.{cpp,h}` will check out any files matching the shell glob pattern `*.{cpp,h}` *in the repository*. Without the backslash, it would have matched against (and expanded to) files *in the current directory*. – Irfy Aug 04 '14 at 09:13
2

For checking out multiple files. I just implemented the wildcards, and it worked well for me. For specific files, we'd probably require a different trick.

I used:

git checkout -- *.*

in my Git Bash. and all the modified files in my workspace were replaced with the ones in the repo.

I hope it helps, thanks.

Divesh
  • 21
  • 2
  • The problem with this is exactly what is pointed out in the accepted answer, that `*` is expanded by the shell (bash, zsh...) to all matching files, which might be none, if you have moved/removed them. While `\*` in this context is expanded by `git` to the files that are tracked by git i.e. `git add` has been applied to them. Even if the files are moved/removed `git checkout \*` will expand to those filenames until you commit moving/removing them. In fact, to commit the removal of `file.end` you have to do `git commit file.end` and yet that file isn't even there (but to git it is). – Jonatan Öström Jan 05 '17 at 11:52
  • That's very true. Thanks Jonatan. Sorry about the noobness – Divesh Mar 31 '17 at 06:28