web-dev-qa-db-fra.com

Déplacer le fichier et le répertoire dans un sous-répertoire avec l'historique de validation

Comment puis-je déplacer un répertoire et des fichiers dans un sous-répertoire avec l'historique de validation?

Par exemple:

  • Structure du répertoire source: [project]/x/[files & sub-dirs]

  • Structure du répertoire cible: [project]/x/p/q/[files & sub-dirs]

64
rst.ptl

Pour ajouter à bmargulies 's comment , la séquence complète est la suivante:

mkdir -p x/p/q      # make sure the parent directories exist first
git mv x/* x/p/q    # move folder, with history preserved
git commit -m "changed the foldername x into x/p/q"

Essayez-le d'abord pour voir un aperçu du déménagement:

git mv -n x/* x/p/q

Wolfgangcommentaires :

Si vous utilisez bash, vous pouvez éviter le problème d'essayer de déplacer un dossier vers lui-même en utilisant un glob étendu tel que so (en utilisant le shopt intégré ):

shopt -s extglob; git mv !(folder) folder

Captain Man rapports dans les commentaires à faire:

mkdir temp 
git mv x/* temp
mkdir -p x/p/q
git mv temp x/p/q
rmdir temp;

Le contexte:

Je suis sur Windows avec Cygwin.
Je viens de me rendre compte que l’exemple shopt -s extglob Était mauvais, alors mon chemin n’est peut-être pas nécessaire, mais j’utilise typiquement zsh au lieu de bash et il n’a pas la commande shopt -s extglob (bien que je sois sûr qu'il existe une alternative), cette approche devrait donc fonctionner pour tous les shells (en remplaçant dans mkdir et rmdir de votre shell s'il est particulièrement étranger)


Comme alternative, spanky mentionne dans les commentaires l'option -k De git mv :

Ignorer le déplacement ou renommer les actions qui pourraient conduire à une condition d'erreur.

git mv -k * target/

Cela éviterait l'erreur "can not move directory into itself".

63
VonC

Git fait un très bon travail pour suivre le contenu même s’il est déplacé, donc git mv est clairement la voie à suivre si vous déplacez des fichiers car ils appartenaient auparavant à x, mais ils appartiennent maintenant à x/p/q parce que le projet a évolué de cette façon.

Parfois, cependant, il existe une raison de déplacer des fichiers vers un sous-répertoire tout au long de l'historique d'un projet. Par exemple, si les fichiers ont été placés quelque part par erreur et que des commits supplémentaires ont été effectués depuis, mais que les commits intermittents n'ont aucun sens si les fichiers sont mal placés. Si tout cela se passait dans une branche locale, nous voulons nettoyer le désordre avant de pousser.

La question dit "avec l'histoire de commettre", ce que j'interprèterais comme une réécriture de l'histoire exactement de cette façon. Cela peut être fait avec

git filter-branch --tree-filter "cd x; mkdir -p p/q; mv [files & sub-dirs] p/q" HEAD

Les fichiers apparaissent alors dans le p/q _ sous-répertoire tout au long de l’histoire.

Veuillez noter que le résultat ne doit pas être transmis à un serveur public si la réécriture touche les validations qui ont déjà été envoyées auparavant.

40
PiQuer

Je peux voir que c'est une vieille question, mais je me sens toujours obligé de répondre à ma solution actuelle au problème, que j'ai tirée de l'un des exemples de git book . Au lieu d'utiliser un inefficace --tree-filter Je déplace les fichiers directement sur l'index avec un --index-filter.

git filter-branch -f --index-filter 'PATHS=`git ls-files -s | sed "s/^<old_location>/<new_location>/"`;GIT_INDEX_FILE=$GIT_INDEX_FILE.new; echo -n "$PATHS" | git update-index --index-info && if [ -e "$GIT_INDEX_FILE.new" ]; then mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"; fi' -- --all

il s'agit d'une spécialisation de l'un des exemples du livre. J'ai également utilisé le même exemple pour renommer en masse des fichiers de l'historique de validation dans un cas particulier. Si vous déplacez des fichiers dans des sous-répertoires: souvenez-vous d'échapper le caractère/dans les chemins d'accès avec un\pour que la commande sed fonctionne comme prévu.

Exemple:

Project Directory
                 |-a
                 |  |-a1.txt
                 |  |-b
                 |  |  |-b1.txt

pour déplacer le répertoire b à la racine du projet:

git filter-branch -f --index-filter 'PATHS=`git ls-files -s | sed "s/a\/b\//b\//"`;GIT_INDEX_FILE=$GIT_INDEX_FILE.new; echo -n "$PATHS" | git update-index --index-info && if [ -e "$GIT_INDEX_FILE.new" ]; then mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"; fi' -- --all

Résultat:

Project Directory
                 |-a
                 |  |-a1.txt
                 |
                 |-b
                 |  |-b1.txt
9
peroyhav

La commande git mv est le moyen le plus simple. Cependant, au moins sur ma machine Linux, je devais fournir le drapeau -k pour éviter de recevoir une erreur indiquant qu’un dossier ne pouvait pas être déplacé sur lui-même. J'ai pu effectuer l'action en utilisant ...

mkdir subdirectory
git mv -k ./* ./subdirectory
# check to make sure everything moved (see below)
git commit

En guise d'avertissement, ceci ignorera les tous mouvements qui pourraient conduire à une condition d'erreur. Vous voudrez donc probablement vérifier que tout a bien fonctionné après le déplacement et avant une validation.

6
Jeremy Hutchins