2017-02-06 4 views
5

Quand je lance le blâme git sur un fichier dans un dossier e, g ,:blâme git sur les fenêtres rapporte "fatale: pas de chemin <path> dans la tête"

git blame Foo/FileA.txt

retourne

fatal: no such path 'Foo/FileA.txt' in HEAD

Je peux voir clairement que ce fichier existe sur le système de fichiers et d'autres fichiers dans le même dossier peut être attribué avec succès - donc ce qui se passe?

Je poste cette question et répondre comme il me avait déconcerté pendant un certain temps aujourd'hui, et je ne pouvais pas trouver une seule réponse qui a frappé l'ensemble de la solution.

Répondre

7

Cela est dû à renommer un dossier parent sur le système de fichiers avec un nouveau nom qui ne varie que par cas - et certains fichiers ont été ajoutés dans un commit se produisant avant le changement de nom du dossier. Voici une repro, à partir d'une invite Powershell:

mkdir C:\RenameProblem 
cd C:\RenameProblem 
git init 
mkdir foo 
"FileA" > foo/FileA.txt 
git add foo/FileA.txt 
git commit -m "Add FileA" 

Puis dans l'explorateur Windows, renommer le répertoire "toto" à "Foo", puis continuer en Powershell avec:

"FileB" > Foo/FileB.txt 
git add Foo/FileB.txt 
git commit -m "Add FileB" 

À ce stade, git blame /Foo/FileA.txt (que l'achèvement de l'onglet générera puisque le dossier a été renommé) échouera avec l'erreur de chemin d'accès tel, alors que git blame /Foo/FileB.txt ou même git blame /foo/FileA.txt réussira.

Futhermore, un appel à git ls-files Foo énumérera seulement FileB.txt et git ls-files foo listera uniquement FileA.txt. Pas un super endroit pour être sur Windows.

Dans mon cas, j'ai eu un grand nombre de fichiers partagés entre les deux versions du nom du dossier.

Vous pouvez résoudre ce problème en renommant le fichier avec git mv:

git mv foo/FileA.txt Foo/FileA.txt 
git commit -am "Rename foo to Foo" 

Si vous avez besoin de renommer un grand nombre de fichiers, utilisez un peu de Powershell (également noter que git mv a un interrupteur -n pour faire « what-if » marche à sec, de sorte que vous pouvez vérifier votre changement de nom est correct):

git ls-files foo | % { (& git mv $_ $('F' + $_.Substring(1))) } 

les utilisations ci-dessus git ls-files pour obtenir une liste de fichiers dans le problème dossier « foo », tuyaux en faire un « foreach » (% i s le raccourci pour cela), puis exécute git mv pour chaque fichier fournissant le nom d'origine ($_) et le nouveau nom de «F» et le reste du nom de fichier ('F' + $_.Substring(1)))