J'ai déplacé un fichier manuellement, puis je l'ai modifié. Selon Git, il s'agit d'un nouveau fichier et d'un fichier supprimé. Existe-t-il un moyen de forcer Git à le traiter comme un transfert de fichier?
Git détectera automatiquement le déplacement/renommer si votre modification n'est pas trop sévère. Juste git add
le nouveau fichier, et git rm
l'ancien fichier. git status
indiquera ensuite s'il a détecté le changement de nom.
en outre, pour les déplacements dans les répertoires, vous devrez peut-être:
git add -A .
git status
pour vérifier que le "nouveau fichier" est maintenant un fichier "renommé"Si le statut de git indique toujours "nouveau fichier" et non "renommé", vous devez suivre Hank Gay’s conseil et effectuer le déplacement et la modification dans deux commits distincts.
Effectuez le déplacement et la modification dans des commits séparés.
Tout est une chose perceptuelle. Git est généralement assez bon pour reconnaître les mouvements, parce que GIT est un traqueur de contenu
Tout ce qui dépend vraiment, c'est comment votre "stat" l'affiche. La seule différence ici est le drapeau -M.
git log --stat -M
commit 9c034a76d394352134ee2f4ede8a209ebec96288
Author: Kent Fredric
Date: Fri Jan 9 22:13:51 2009 +1300
Category Restructure
lib/Gentoo/Repository.pm | 10 +++++-----
lib/Gentoo/{ => Repository}/Base.pm | 2 +-
lib/Gentoo/{ => Repository}/Category.pm | 12 ++++++------
lib/Gentoo/{ => Repository}/Package.pm | 10 +++++-----
lib/Gentoo/{ => Repository}/Types.pm | 10 +++++-----
5 files changed, 22 insertions(+), 22 deletions(-)
git log --stat
commit 9c034a76d394352134ee2f4ede8a209ebec96288
Author: Kent Fredric
Date: Fri Jan 9 22:13:51 2009 +1300
Category Restructure
lib/Gentoo/Base.pm | 36 ------------------------
lib/Gentoo/Category.pm | 51 ----------------------------------
lib/Gentoo/Package.pm | 41 ---------------------------
lib/Gentoo/Repository.pm | 10 +++---
lib/Gentoo/Repository/Base.pm | 36 ++++++++++++++++++++++++
lib/Gentoo/Repository/Category.pm | 51 ++++++++++++++++++++++++++++++++++
lib/Gentoo/Repository/Package.pm | 41 +++++++++++++++++++++++++++
lib/Gentoo/Repository/Types.pm | 55 +++++++++++++++++++++++++++++++++++++
lib/Gentoo/Types.pm | 55 -------------------------------------
9 files changed, 188 insertions(+), 188 deletions(-)
journal d'aide git
-M
Detect renames.
-C
Detect copies as well as renames. See also --find-copies-harder.
git diff -M
ou git log -M
devrait automatiquement détecter ces modifications comme étant un renommer avec des modifications mineures tant qu'elles sont en réalité . Si vos modifications mineures ne sont pas mineures, vous pouvez réduire la similarité, par exemple.
$ git log -M20 -p --stat
pour le réduire de la valeur par défaut de 50% à 20%.
Voici une solution rapide et simplifiée pour un ou plusieurs fichiers renommés et modifiés non validés.
Supposons que le fichier s'appelle foo
et qu'il s'appelle maintenant bar
:
Renommez bar
en un nom temporaire:
mv bar side
Commander foo
:
git checkout HEAD foo
Renommez foo
en bar
avec Git:
git mv foo bar
Maintenant, renommez votre fichier temporaire en bar
.
mv side bar
C'est cette dernière étape qui récupère le contenu modifié dans le fichier.
Bien que cela puisse fonctionner, si le fichier déplacé est trop différent du contenu du git original, il sera plus efficace de décider qu'il s'agit d'un nouvel objet. Permettez-moi de démontrer:
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
renamed: README -> README.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
modified: work.js
$ git add README.md work.js # why are the changes unstaged, let's add them.
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
deleted: README
new file: README.md
modified: work.js
$ git stash # what? let's go back a bit
Saved working directory and index state WIP on dir: f7a8685 update
HEAD is now at f7a8685 update
$ git status
On branch workit
Untracked files:
(use "git add <file>..." to include in what will be committed)
.idea/
nothing added to commit but untracked files present (use "git add" to track)
$ git stash pop
Removing README
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
new file: README.md
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: README
modified: work.js
Dropped refs/stash@{0} (1ebca3b02e454a400b9fb834ed473c912a00cd2f)
$ git add work.js
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
new file: README.md
modified: work.js
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: README
$ git add README # hang on, I want it removed
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
deleted: README
new file: README.md
modified: work.js
$ mv README.md Rmd # Still? Try the answer I found.
$ git checkout README
error: pathspec 'README' did not match any file(s) known to git.
$ git checkout HEAD README # Ok the answer needed fixing.
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
new file: README.md
modified: work.js
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: README.md
modified: work.js
Untracked files:
(use "git add <file>..." to include in what will be committed)
Rmd
$ git mv README README.md
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
renamed: README -> README.md
modified: work.js
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: work.js
Untracked files:
(use "git add <file>..." to include in what will be committed)
Rmd
$ mv Rmd README.md
$ git status
On branch workit
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitignore
renamed: README -> README.md
modified: work.js
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
modified: work.js
$ # actually that's half of what I wanted; \
# and the js being modified twice? Git prefers it in this case.
Si vous parlez de git status
n'indiquant pas les renames, essayez plutôt git commit --dry-run -a
Si vous utilisez TortoiseGit, il est important de noter que la détection de renommage automatique de Git a lieu lors de la validation, mais le fait que cela va se produire n'est pas toujours affiché par le logiciel à l'avance. J'avais déplacé deux fichiers dans un répertoire différent et effectué de légères modifications. J'utilise TortoiseGit comme outil de validation et la liste Modifications apportées indique les fichiers en cours de suppression et d’ajout, pas déplacés. L'exécution du statut git à partir de la ligne de commande a montré une situation similaire. Cependant, après avoir validé les fichiers, ils ont été renommés dans le journal. La réponse à votre question est donc, tant que vous n'avez rien fait de trop drastique, Git devrait automatiquement reprendre le changement de nom.
Éditer: Apparemment, si vous ajoutez les nouveaux fichiers puis effectuez un statut git à partir de la ligne de commande, le renom doit apparaître avant la validation.
Edit 2: De plus, dans TortoiseGit, ajoutez les nouveaux fichiers dans la boîte de dialogue de validation, mais ne les validez pas. Ensuite, si vous allez dans la commande Afficher le journal et consultez le répertoire de travail, vous verrez si Git a détecté le changement de nom avant la validation.
La même question a été soulevée ici: https://tortoisegit.org/issue/1389 et a été enregistrée en tant que bogue à corriger ici: https://tortoisegit.org/issue/1440 Il s’agit d’un problème d’affichage avec la boîte de dialogue de validation de TortoiseGit et existe en quelque sorte dans le statut git si vous n'avez pas ajouté les nouveaux fichiers.
Utilisez la commande git mv
pour déplacer les fichiers au lieu des commandes de déplacement du système d'exploitation: https://git-scm.com/docs/git-mv
Notez que la commande git mv
n'existe que dans les versions 1.8.5 et supérieures de Git. Vous devrez donc peut-être mettre à jour votre Git pour utiliser cette commande.
Ou vous pouvez essayer la réponse à cette question ici avec Ambre ! Pour le citer encore:
Tout d’abord, annulez votre ajout par étapes pour le fichier déplacé manuellement:
$ git reset path/to/newfile
$ mv path/to/newfile path/to/oldfile
Ensuite, utilisez Git pour déplacer le fichier:
$ git mv path/to/oldfile path/to/newfile
Bien sûr, si vous avez déjà validé le déplacement manuel, vous souhaiterez peut-être réinitialiser la révision avant le déplacement, puis simplement git mv à partir de là.
J'ai eu ce problème récemment, lors du déplacement (sans modification) de certains fichiers.
Le problème est que Git a modifié certaines fins de ligne lorsque j'ai déplacé les fichiers et qu'il n'a pas été en mesure de dire que les fichiers étaient les mêmes.
Utiliser git mv
a réglé le problème, mais cela ne fonctionne que sur des fichiers/répertoires uniques, et j'avais beaucoup de fichiers à faire à la racine du référentiel.
Une façon de résoudre ce problème serait d'utiliser une magie bash/batch.
Une autre façon est la suivante
git commit
. Ceci met à jour les fins de ligne.git commit --amend
git commit --amend
. Il n'y a pas de changement aux fins de ligne cette fois, donc Git est heureuxPour moi, cela a fonctionné pour sauvegarder toutes les modifications avant le commit et les ressortir. Cela a permis à Git de ré-analyser les fichiers ajoutés/supprimés et de les marquer correctement comme déplacés.
Il existe probablement une meilleure méthode de «ligne de commande» pour le faire, et je sais que c’est un hack, mais je n’ai jamais réussi à trouver une bonne solution.
Utilisation de TortoiseGIT: Si vous avez une validation GIT dans laquelle certaines opérations de déplacement de fichier apparaissent sous la forme de charges d’ajouts/suppressions plutôt que de renommements, même si les fichiers ne contiennent que de petites modifications, procédez comme suit:
Le nouveau commit affichera maintenant correctement les renominations de fichiers… ce qui aidera à conserver un historique correct des fichiers.
Je comprends cette question comme "Comment faire en sorte que git reconnaisse la suppression d’un ancien fichier et la création d’un nouveau fichier en tant que déplacement de fichier".
Oui dans le répertoire de travail une fois que vous avez supprimé un ancien fichier et inséré un ancien fichier, git status
dira "deleted: old_file
" et "Untracked files: ... new_file
"
Mais dans l'index/le niveau intermédiaire, une fois que vous avez ajouté et supprimé un fichier à l'aide de git, il sera reconnu comme un déplacement de fichier. Pour ce faire, en supposant que vous ayez effectué la suppression et la création à l'aide de votre système d'exploitation, exécutez les commandes suivantes:
git add new_file
git rm old_file
Si le contenu du fichier est identique à 50% ou plus, exécuter la commande git status
devrait vous donner:
renamed: old_file -> new_file
Lorsque je modifie, renomme et déplace un fichier en même temps, aucune de ces solutions ne fonctionne. La solution consiste à le faire en deux commits (éditer et renommer/déplacer séparément) puis à fixup
le deuxième commit via git rebase -i
pour l'avoir dans un commit.