Is there a way to use wildcards with git checkout?

GitWildcardGit Checkout

Git Problem Overview


What I would like to do is to checkout a single file or a set of files with a common name part like this

git checkout myBranch */myFile.md and

git checkout myBranch -- */*Test* (not sure about the '--' part)

instead of

git checkout myBranch src/main/java/a/deep/package/structure/myFile.md and

git checkout myBranch src/test/java/a/deep/package/structure/TestOne.java
git checkout myBranch src/test/java/a/deep/package/structure/TestTwo.java
git checkout myBranch src/test/java/a/deep/package/structure/resources/TestData.sql

I know there is some limited wildcard functionality for some git command like diff and add but have found nothing for checkout. Is there a way?

EDIT: I am using git 1.7.9.5 on Linux. A working combination of git and shell commmands would be acceptable as well.

Git Solutions


Solution 1 - Git

Git does deal with wildcards, using fnmatch(3). See the pathspec entry in Git glossary.

But to be sure that git can see the wildcards, they must be escaped otherwise your shell will expand them first. Typically, I use wildcards between single-quotes:

git checkout myBranch -- '*/myFile.md'

The wildcards are applied to the whole name, directories included.

As you can see in the documentation, the pathspec also allows magic signature which change how to interpret the pathspec. For example, you can have case-insensitive paths with icase (you can type ':(icase)*readme*' to find all your readme's).

I quote @bambams's comment here, in case you have problems in Windows:

> This is not working for me in Windows with 2.8.1.windows.1 and I'm > utilizing Git from the cmd.exe shell so no globbing built in. There is > however a solution if you're in such a sorry state. Combine git diff --name-only and xargs to achieve your goal:

> git diff --name-only -- ... | xargs git checkout

Solution 2 - Git

Git does not deal with the wildcard, but your shell does.

Try this :

git checkout myBranch **/myFile.md

and

git checkout myBranch  **/*Test*

With the **, your shell will look for files in all the subdirectories starting from the current working directory.

Solution 3 - Git

Powershell

@(gci -Recurse *test* | Resolve-Path -Relative) | %{git checkout mybranch -- $_)

gci generates a list of all files matching the criteria (*test*) then pipes it to Resolve-Path to get the relative path. Finally the flattened (@) list of filenames is piped into the git invokation (executes once per file found).

Solution 4 - Git

Windows git bash with xargs

git difftool myBranch --name-only *.java | xargs git checkout myBranch

Solution 5 - Git

None of the other answers worked for me, but bambams comment worked. I made it into a bash function that accepts two args. Usage:

gitcheckout myBranch '*file*'

gitcheckout()
{
    GIT_DIR=$(git rev-parse --git-dir 2>/dev/null); 
    pushd .;
    cd $GIT_DIR/../;
    git diff --name-only $1 -- $2 | xargs git checkout $1 --;
    popd;
}

Solution 6 - Git

If you have a gitignore or untracked files and you want to use wildcards with git checkout, then it might give you problems, and a solution could be:

git ls-files '*/myFile.md' | tr '\n' '\0' | xargs -0 -L1 -I '$' git checkout -- '$'

Solution 7 - Git

Knowing that git returns branch list names from 3rd char, one can just switch to needed branch defined via [mask]:

BRANCH_NAME=$(git branch --list | grep [mask] | cut -c3-)
git checkout ${BRANCH_NAME}

Solution 8 - Git

For me the task was to checkout several files named after one pattern:

  • ./a/b/c/FirstTest.java
  • .d/e/f/SecondTest.java
  • ./g/h/i/ThirdTest.java

I've used this bash command:

# 1. Find files named after "*Test.java" pattern.
# 2. Execute checkout command on every found file.

find . -name "*Test.java" -exec git checkout master {} \;

Also firstly you can test the find command with simple echo, which just prints a given text ({} in our case, which will be replaced with current found filename by shell):

find . -name "*Test.java" -exec echo {} \;

Solution 9 - Git

If you need to get the files from a commit regardless of whether they were changed in that commit, you can use the following:

git ls-tree --name-only -r myBranch | grep myFilePattern | xargs git checkout myBranch

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkostjaView Question on Stackoverflow
Solution 1 - GitcoredumpView Answer on Stackoverflow
Solution 2 - GitIntrepiddView Answer on Stackoverflow
Solution 3 - Git9Rune5View Answer on Stackoverflow
Solution 4 - GitSarathView Answer on Stackoverflow
Solution 5 - GitKlikView Answer on Stackoverflow
Solution 6 - GitferdymercuryView Answer on Stackoverflow
Solution 7 - GitIvan MView Answer on Stackoverflow
Solution 8 - GitYamashiro RionView Answer on Stackoverflow
Solution 9 - GitJohn MichelauView Answer on Stackoverflow