how do I clone files with colons in the filename

Good news.
Technically, the answer to “how do I clone files with colons in the filename” is to simply use “git clone”. Luckily it is only the checkout that fails on Windows (even under msysgit) and there is a rather clean workaround for this shown below.

TL;DR

in Git Bash…

git clone {repo URL}
cd {repo dir}
git ls-tree -r master --name-only | grep -v ":" | xargs git reset HEAD
git commit -m "deleting all files with a colon in the name"
git restore .

… and then

  • download the Zip of the whole git repo
  • rename files with colons inside the Zip (without extracting them)
  • extract just those files you renamed
  • add those renamed files to your working directory

For insight into those few steps listed above, please keep reading….

I was able to work around this issue while working with a repo with colons in various filenames. The following worked for me:

  • Do a regular git clone.

$ git clone https://github.com/wdawson/dropwizard-auth-example.git

You should see the following error that notes that the clone succeeded, but the checkout failed.

Cloning into 'dropwizard-auth-example'...
remote: Enumerating objects: 322, done.
remote: Total 322 (delta 0), reused 0 (delta 0), pack-reused 322
Receiving objects: 100% (322/322), 15.00 MiB | 2.88 MiB/s, done.
Resolving deltas: 100% (72/72), done.
error: invalid path 'src/test/resources/revoker/example-ca/certs/root.localhost:9000.cert.pem'
fatal: unable to checkout working tree
warning: Clone succeeded, but checkout failed.
You can inspect what was checked out with 'git status'
and retry with 'git restore --source=HEAD :/'
  • Change directories to the new cloned repo

cd dropwizard-auth-example

  • Check that the git repo working directory is completely empty

ls

  • Run git-status to find that all the files are staged for deletion

$ git status

Output…

On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    .gitignore
        deleted:    .travis.yml
        deleted:    LICENSE
        deleted:    NOTICE
        deleted:    README.md
        deleted:    conf.yml
...
  • Revert the staged deletion of only the files that do not contain a colon in the file name.

$ git ls-tree -r master --name-only | grep -v ":" | xargs git reset HEAD

Output…

Unstaged changes after reset:
D       .gitignore
D       .travis.yml
D       LICENSE
D       NOTICE
D       README.md
D       conf.yml
D       java-cacerts.jks
D       pom.xml
D       src/main/java/wdawson/samples/dropwizard/UserInfoApplication.java
D       src/main/java/wdawson/samples/dropwizard/api/UserInfo.java
D       src/main/java/wdawson/samples/dropwizard/auth/OAuth2Authenticator.java
D       src/main/java/wdawson/samples/dropwizard/auth/OAuth2Authorizer.java
D       src/main/java/wdawson/samples/dropwizard/auth/Role.java
...
  • Run git status again to see that only the files that contain a colon in the file name are now staged for deletion. All other files are still showing as deleted, but not staged for commit. This is what we want at this stage.

$ git status

Output…

On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    src/test/resources/revoker/example-ca/certs/root.localhost:9000.cert.pem
        deleted:    src/test/resources/revoker/example-ca/csr/root.localhost:9000.csr.pem
        deleted:    src/test/resources/revoker/example-ca/intermediate/certs/intermediate.localhost:9000.cert.pem
        deleted:    src/test/resources/revoker/example-ca/intermediate/csr/intermediate.localhost:9000.csr.pem
        deleted:    src/test/resources/revoker/example-ca/intermediate/private/intermediate.localhost:9000.key.pem
        deleted:    src/test/resources/revoker/example-ca/private/root.localhost:9000.key.pem

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    .gitignore
        deleted:    .travis.yml
        deleted:    LICENSE
        deleted:    NOTICE
        deleted:    README.md
        deleted:    conf.yml
        deleted:    java-cacerts.jks
        deleted:    pom.xml
  • Commit all the staged files. That is, commit the deletion of all the files that contain a colon in the file name.

git commit -m "deleting all files with a colon in the name"

  • Restore everything in the working directory.

$ git restore .

  • View all the files. What a beautiful site.

$ ls

Output…

conf.yml java-cacerts.jks LICENSE NOTICE pom.xml README.md src

Once you’ve deleted the offending files from your working directory…

  • download a Zip of the whole GitHub repo
  • open it up in 7Zip… Don’t unzip it … just open it for editing (to rename files)
  • find the files that have a colon in the name
  • rename each file with a colon replacing the colon with an underscore…or whatever is appropriate
  • now you can extract those files you just renamed
  • copy them into the git working directory

PS: All of the above was done in GitBash on Windows 10 using git version 2.25.1.windows.1. Similar steps can be done via the GUI using TortoiseGit on Windows.

Leave a Comment