Comment copier une version d'un fichier unique d'une branche git vers une autre?

944

J'ai deux branches qui sont complètement fusionnées.

Cependant, après la fusion, je me rends compte qu'un fichier a été gâché par la fusion (quelqu'un d'autre a fait un formatage automatique, gah), et il serait simplement plus facile de passer à la nouvelle version dans l'autre branche, et puis réinsérez mon changement d'une ligne après l'avoir transféré dans ma branche.

Alors, quelle est la façon la plus simple de le faire avec git?

madlep
la source
3
Veuillez noter que dans la réponse acceptée, la première solution met en scène les modifications, et la deuxième solution ne le fait pas. stackoverflow.com/a/56045704/151841
user151841

Réponses:

1675

Exécutez cela à partir de la branche où vous souhaitez que le fichier se termine:

git checkout otherbranch myfile.txt

Formules générales:

git checkout <commit_hash> <relative_path_to_file_or_dir>
git checkout <remote_name>/<branch_name> <file_or_dir>

Quelques notes (des commentaires):

  • En utilisant le hachage de validation, vous pouvez extraire des fichiers de n'importe quel commit
  • Cela fonctionne pour les fichiers et les répertoires
  • écrase le fichier myfile.txtetmydir
  • Les caractères génériques ne fonctionnent pas, mais les chemins relatifs le font
  • Plusieurs chemins peuvent être spécifiés

une alternative:

git show commit_id:path/to/file > path/to/file
madlep
la source
13
Oui, bien sûr. Mais c'était l'intention de la question.
Ikke
37
Probablement évident, mais vous devez utiliser le nom de fichier complet ... Les caractères génériques ne fonctionnent pas!
Chris Hart
6
bien que .. c'est aussi une bonne façon: git show commit_id: chemin / vers / fichier> chemin / vers / fichier
milushov
14
remote: git checkout origin / otherbranch myfile.txt
Roman Rhrn Nesterov
6
L'utilisation de caractères génériques fonctionne, il vous suffit de les envelopper ''afin qu'ils ne soient pas interprétés par le shell.
Wiktor Czajkowski
82

Je me suis retrouvé à cette question sur une recherche similaire. Dans mon cas, je cherchais à extraire un fichier d'une autre branche dans le répertoire de travail actuel qui était différent de l'emplacement d'origine du fichier. Réponse :

git show TREEISH:path/to/file >path/to/local/file
lkraav
la source
18
L'intention de «git show» est de sortir les données vers le terminal dans un format lisible, qui n'est pas garanti pour correspondre exactement au contenu du fichier. Même chose qu'il vaut mieux copier un document Word dans son ensemble et ne pas essayer de copier-coller son contenu dans un autre document.
Gonen
Je voulais juste le voir pour pouvoir comparer le contenu avec la branche actuelle (vérifier un morceau de code). J'aimerais utiliser vim avec cela cependant ... pour la coloration syntaxique, etc.
isaaclw
3
Pour comparer le contenu avant de passer à la caisse, git diff <other branch> <path to file>fonctionne bien.
Randall
2
@Gonen: Depuis la version 2.21.0 de git, la page de manuel "git show" indique "Pour les blobs simples, il affiche le contenu simple." Je ne sais pas si cela signifie que nous sommes toujours bons. Je me méfie un peu de récupérer une image de cette façon ...
hibbelig
52

Qu'en est-il de l'utilisation de la commande de paiement:

  git diff --stat "$branch"
  git checkout --merge "$branch" "$file"
  git diff --stat "$branch"
RzR
la source
8
la fusion de notes (2ème commande) ne peut pas fonctionner si le fichier n'existe pas sur les deux branches
simpleuser
Hm. Je n'ai pas de diffstat. Est-ce une version spécifique d'un outil de diff, car je n'en ai jamais entendu parler (et devrais-je y passer?): D
dudewad
git diffsupporte un --statargument qui fait essentiellement la même chose que diffstat.
hlovdal
J'ai dû faire vérifier les deux succursales localement pour que cela fonctionne.
UnitasBrooks
18

1) Assurez-vous que vous êtes dans la succursale où vous avez besoin d'une copie du fichier. par exemple: je veux un fichier de sous-branche dans le maître, vous devez donc commander ou devrait être dans le maîtregit checkout master

2) Maintenant, retirez le fichier spécifique que vous voulez de la sous-branche au maître,

git checkout sub_branch file_path/my_file.ext

ici sub_branchsignifie où vous avez ce fichier suivi du nom du fichier que vous devez copier.

Mohideen bin Mohammed
la source
Très pratique et bien expliqué.
Abk
15

Après la réponse de madlep, vous pouvez également copier un répertoire d'une autre branche avec le blob de répertoire.

git checkout other-branch app/**

Quant à la question de l'op si vous n'avez modifié qu'un seul fichier, cela fonctionnera bien ^ _ ^

6ft Dan
la source
1
Notez que les deux branches doivent d'abord être correctement tirées ou utilisées origin/other-branchpour faire référence à la branche repo. Bases, mais mord moi. (la réponse est excellente - aucune modification requise)
akauppi
8

J'utiliserais git restore(disponible depuis git 2.23)

git restore --source otherbranch path/to/myfile.txt


Pourquoi c'est mieux que d'autres options?

git checkout otherbranch -- path/to/myfile.txt- Il copie le fichier dans le répertoire de travail mais aussi dans la zone de transit (effet similaire à si vous vouliez copier ce fichier manuellement et exécuté git adddessus). git restorene touche pas la zone de rassemblement (sauf indication contraire de l' --stagedoption).

git show otherbranch:path/to/myfile.txt > path/to/myfile.txtutilise la redirection standard du shell. Si vous utilisez Powershell, il peut y avoir un problème de liaison de texte ou vous pouvez obtenir un fichier cassé s'il est binaire . Avec la git restoremodification des fichiers se fait tout par gitexécutable.

Un autre avantage est que vous pouvez restaurer un dossier entier avec:

git restore --source otherbranch path/to

ou avec git restore --overlay --source otherbranch path/tosi vous voulez éviter de supprimer des fichiers. Par exemple, s'il y a moins de fichiers otherbranchque dans le répertoire de travail actuel (et que ces fichiers sont suivis ) sans --overlayoption, ils git restoreseront supprimés. Mais c'est un bon comportement par défaut, vous voudrez probablement que l'état du répertoire soit le même que dans otherbranch, pas "le même mais avec des fichiers supplémentaires dans ma branche actuelle"

Mariusz Pawelski
la source
Bonne réponse. Existe-t-il un git restoremoyen de copier un fichier de la branche source vers un nouveau fichier sur la branche cible? Avec git show, je peux le faire avec la redirection de shell ( git show otherbranch:path/to/file1.txt > path/to/file2.txt), mais je veux éviter la redirection de shell pour les raisons que vous avez mentionnées.
AdmiralAdama
1
@AdmiralAdama pas vraiment. Et je pense qu'il n'y a pas de grande chance d'y entrer git restore(mais qui sait;)). Ces problèmes de redirection sont essentiellement un problème Powershell, je ne sais pas s'il y a un autre shell qui a un problème avec lui. Je reviens habituellement à "git bash" ou même "cmd" où j'ai besoin d'utiliser les commandes " git showavec redirection". Ou utilisez une interface graphique comme GitExtensions où vous pouvez parcourir l'arborescence des fichiers de validation et cliquez sur "Enregistrer sous" sur n'importe quel fichier.
Mariusz Pawelski
Ah, je vois. Je n'utilise pas Powershell, donc la redirection du shell est peut-être np pour moi. Merci pour l'info.
Amiral Adama
3

Veuillez noter que dans la réponse acceptée, la première option met en scène l'intégralité du fichier de l'autre branche (comme cela git add ...avait été fait), et que la deuxième option entraîne simplement la copie du fichier, mais ne met pas en scène les modifications (comme si vous aviez juste édité le fichier manuellement et avait des différences remarquables).

Git copier le fichier d'une autre branche sans le mettre en scène

Modifications par étapes (par exemple git add filename):

$ git checkout directory/somefile.php feature-B

$ git status
On branch feature-A
Your branch is up-to-date with 'origin/feature-A'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   directory/somefile.php

Modifications en suspens (non échelonnées ou engagées):

$ git show feature-B:directory/somefile.php > directory/somefile.php

$ git status
On branch feature-A
Your branch is up-to-date with 'origin/feature-A'.
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:   directory/somefile.php

no changes added to commit (use "git add" and/or "git commit -a")
user151841
la source
J'obtiens "la fonctionnalité-B n'est pas un fichier", le nom de la branche vient en premier, à ce sujet -> "> répertoire / unfichier.php" cela peut-il changer l'encodage du fichier?
Tiago Oliveira de Freitas