Le mois dernier, j'ai commencé à contribuer à un dépôt GitHub en annulant le repo correspondant, en créant une branche de fonctionnalité et en soumettant une requête pull. En répétant ce processus pendant quelques jours, j'ai rencontré un problème étrange en renommant les fichiers avec la commande Linux pré-installée mv
et aussi avec la commande Git git mv
.Comportement Odd `git mv`
Le problème réel est que selon le moment où vous déplacer/renommer un fichier avec git mv
, lorsque vous git add
et à quel point vous modifiez le fichier renommé, soit vous obtenez:
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: somethingelse -> something
Ou ceci:
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: something
deleted: somethingelse
Pour le démontrer, j'ai écrit un test:
#!/bin/bash
# To my knowledge, this “problem” only occurs with new files in a Git repo
printf "COMMAND: mkdir -v gitrepo\n\n"
mkdir -v gitrepo
printf "\nCOMMAND: cd gitrepo\n\n"
cd gitrepo
printf "\nCOMMAND: git init\n\n"
git init
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: touch something\n\n"
touch something
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git add something\n\n"
git add something
printf "\nCOMMAND: git status\n\n"
git status
printf '\nCOMMAND: git commit -m "Added something"\n\n'
git commit -m "Added something"
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git mv something somethingelse\n\n"
git mv something somethingelse
printf "\nCOMMAND: git status\n\n"
git status
# Type in the following on line 1: First line of code
printf "\nCOMMAND: vim somethingelse\n\n"
vim somethingelse
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git add somethingelse\n\n"
git add somethingelse
printf "\nCOMMAND: git status\n\n"
git status
printf '\nCOMMAND: git commit -m "Renamed something to somethingelse and edited somethingelse"\n\n'
git commit -m "Renamed something to somethingelse and edited somethingelse"
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git mv somethingelse something\n\n"
git mv somethingelse something
printf "\nCOMMAND: git status\n\n"
git status
# If you add something to the first line, the rename will not be detected by Git
# However, if you instead create 2 newlines and fill line 3 with new code,
# the rename gets detected for whatever reason
printf "\nCOMMAND: vim something\n\n"
vim something
printf "\nCOMMAND: git status\n\n"
git status
printf "\nCOMMAND: git add something\n\n"
git add something
printf "\nCOMMAND: git status\n\n"
git status
printf '\nCOMMAND: git commit -m "Renamed somethingelse to something and edited something"\n\n'
git commit -m "Renamed somethingelse to something and edited something"
printf "\nCOMMAND: git status\n\n"
git status
cd .. && rm -fr gitrepo && printf "\nREMOVED gitrepo folder\n"
printf "\nDONE.\n"
Pour une raison quelconque, cela affecte principalement les «nouveaux fichiers» et non ceux qui existent déjà dans un référentiel. Si vous clonez ma branche du Spoon-Knife repository par exemple avec git clone https://github.com/christianheinrichs/Spoon-Knife.git
puis que vous appliquez le flux de travail du script de test lié, vous verrez que dans la plupart des cas, vous pourrez renommer le fichier README.md en README par exemple, le modifier et il sera toujours considéré comme un changement de nom au lieu d'un nouveau fichier/segment supprimé. Bien que je puisse reproduire le nouveau comportement de fichier/supprimé sur le repo de fourchette Spoon-Knife cloné, je ne suis pas sûr exactement comment je l'ai fait et croyez-moi quand je dis que j'ai essayé de le comprendre.
Alors que se passe-t-il exactement ici que je ne comprends pas?
Voir: https://gist.github.com/christianheinrichs/e50bfdd5eec70a606fa6ce4a88c5951b#file-git_mv-test-sh-L65
Notez également que lorsque vous exécutez 'git diff' vous pouvez activer ou désactiver la détection renommer, et définir le nombre « seuil de similarité ». Lorsque 'git status' exécute' git diff' pour vous, dans ce cas, il définit le seuil de similarité sur 50%: la détection du renommage est toujours activée et le seuil est fixé. – torek
@torek Je suppose que vous parlez de 'git diff -M [], --find-renames [= ]'? C'est une caractéristique intéressante que je ne connaissais pas et qui pourrait partiellement expliquer le problème dans ma deuxième question. –
@LeGEC Merci pour votre réponse. Cependant, avant de l'accepter, pouvez-vous expliquer le comportement de Git dans la deuxième question que j'ai jointe? 'Aussi, pourquoi Git ne détecte-t-il pas le renommer si vous ajoutez quelque chose à la première ligne, mais si vous créez 2 lignes et remplissez la ligne 3 avec le nouveau code?' –