Como copiar uma versão de um único arquivo de uma ramificação git para outra?

944

Eu tenho dois ramos totalmente fundidos.

No entanto, depois que a mesclagem é concluída, percebo que um arquivo foi danificado pela mesclagem (alguém fez um formato automático, gah), e seria mais fácil mudar para a nova versão no outro ramo e reinsira minha alteração de uma linha depois de trazê-la para o meu ramo.

Então, qual é a maneira mais fácil no git de fazer isso?

madlep
fonte
3
Observe que, na resposta aceita, a primeira solução realiza as alterações e a segunda solução não. stackoverflow.com/a/56045704/151841
user151841

Respostas:

1675

Execute isso a partir da ramificação em que você deseja que o arquivo termine:

git checkout otherbranch myfile.txt

Fórmulas gerais:

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

Algumas notas (dos comentários):

  • Usando o hash de confirmação, você pode obter arquivos de qualquer confirmação
  • Isso funciona para arquivos e diretórios
  • sobrescreve o arquivo myfile.txtemydir
  • Os curingas não funcionam, mas os caminhos relativos
  • Vários caminhos podem ser especificados

uma alternativa:

git show commit_id:path/to/file > path/to/file
madlep
fonte
13
Sim, seria. Mas essa era a intenção da pergunta.
Ikke
37
Provavelmente óbvio, mas você precisa usar o nome completo do arquivo ... Os curingas não funcionam!
Chris Hart
6
embora .. também é boa maneira: git show de commit_id: path / to / file> path / to / file
milushov
14
remote: origem do checkout do git / otherbranch myfile.txt
Roman Rhrn Nesterov 4/13
6
O uso de curingas funciona, basta envolvê-los ''para que não sejam interpretados pelo shell.
Wiktor Czajkowski
82

Eu acabei com essa pergunta em uma pesquisa semelhante. No meu caso, eu estava procurando extrair um arquivo de outra ramificação para o diretório de trabalho atual diferente da localização original do arquivo. Resposta :

git show TREEISH:path/to/file >path/to/local/file
lkraav
fonte
18
A intenção do 'git show' é enviar dados para o terminal em formato legível, o que não é garantido para corresponder exatamente ao conteúdo do arquivo. Da mesma forma que é melhor copiar um documento do word como um todo, e não tentar copiar e colar seu conteúdo em outro documento.
Gonen
Eu só queria visualizá-lo para poder comparar o conteúdo com a ramificação atual (verifique um pedaço de código). Eu gostaria de usar o vim com este embora ... para destaque de sintaxe, etc.
isaaclw
3
Para comparar o conteúdo antes de fazer o checkout, git diff <other branch> <path to file>funciona bem.
Randall
2
@ Gonen: A partir da versão 2.21.0 do git, a página de manual "git show" diz "Para blobs simples, mostra o conteúdo simples". Não tenho certeza se isso significa que somos sempre bons. Eu estou meio desconfiado para buscar uma imagem dessa forma ...
hibbelig
52

Que tal usar o comando checkout:

  git diff --stat "$branch"
  git checkout --merge "$branch" "$file"
  git diff --stat "$branch"
RzR
fonte
8
merge nota (2ª comando) pode não funcionar se o arquivo não existe em ambos os ramos
simpleuser
Hum. Eu não tenho diffstat. Essa é uma versão específica de uma ferramenta diff, porque eu nunca ouvi falar dela (e devo mudar para ela?): D
dudewad
git diffsuporta um --statargumento que basicamente faz a mesma coisa que diffstat.
Hjdaldal 01/07/19
Eu precisava que os dois ramos fossem verificados localmente para que isso funcionasse.
precisa saber é o seguinte
18

1) Verifique se você está no ramo onde precisa de uma cópia do arquivo. por exemplo: eu quero o arquivo sub branch no master, então você precisa fazer o checkout ou deve estar no mastergit checkout master

2) Agora faça o check-out do arquivo específico que você deseja da sub ramificação para a master,

git checkout sub_branch file_path/my_file.ext

aqui sub_branchsignifica onde você tem esse arquivo seguido pelo nome do arquivo que você precisa copiar.

Mohideen bin Mohammed
fonte
Muito útil e bem explicado.
Abk
15

Após a resposta do madlep, você também pode copiar um diretório de outro ramo com o blob de diretório.

git checkout other-branch app/**

Quanto à pergunta do op, se você apenas alterou um arquivo, isso funcionará bem ^ _ ^

6ft Dan
fonte
1
Observe que os dois ramos precisam ser puxados corretamente, primeiro ou usados origin/other-branchpara se referir ao ramo de recompra. Noções básicas, mas me mordeu. (a resposta é grande - nenhuma edição obrigatório)
akauppi
8

Eu usaria git restore(disponível desde o git 2.23)

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


Por que é melhor do que outras opções?

git checkout otherbranch -- path/to/myfile.txt- Copia o arquivo para o diretório de trabalho, mas também para a área intermediária (efeito semelhante como se você copiasse esse arquivo manualmente e o executasse git add). git restorenão toca na área de armazenamento temporário (a menos que seja solicitado por --stagedopção).

git show otherbranch:path/to/myfile.txt > path/to/myfile.txtusa redirecionamento de shell padrão. Se você usa o Powershell, pode haver um problema com a entrada de texto ou você pode obter um arquivo quebrado, se for binário . Com a git restoremudança de arquivos é feito tudo pelo gitexecutável.

Outra vantagem é que você pode restaurar a pasta inteira com:

git restore --source otherbranch path/to

ou com git restore --overlay --source otherbranch path/tose você quiser evitar a exclusão de arquivos. Por exemplo, se houver menos arquivos do otherbranchque no diretório de trabalho atual (e esses arquivos forem rastreados ) sem a --overlayopção git restore, eles serão excluídos. Mas esse é um bom comportamento padrão; é provável que você queira que o estado do diretório seja o mesmo de otherbranch, não "o mesmo, mas com arquivos adicionais no meu ramo atual"

Mariusz Pawelski
fonte
Boa resposta. Existe uma git restoremaneira de copiar um arquivo da ramificação de origem para um novo arquivo na ramificação de destino? Com o git show, posso fazer isso com o redirecionamento de shell ( git show otherbranch:path/to/file1.txt > path/to/file2.txt), mas quero evitar o redirecionamento de shell pelos motivos mencionados.
AdmiralAdama
1
@AdmiralAdama na verdade não. E acho que não há grande chance de conseguir git restore(mas quem sabe;)). Esses problemas de redirecionamento são basicamente um problema do PowerShell, não tenho certeza se existe algum outro shell com problema. Normalmente, volto ao "git bash" ou até ao "cmd", onde preciso usar os git showcomandos " com redirecionamento". Ou use a GUI como GitExtensions, onde você pode procurar na árvore de arquivos de confirmação e clicar em "Salvar como" em qualquer arquivo.
Mariusz Pawelski
Ah entendo. Eu não uso o Powershell, então talvez o redirecionamento de shell seja np para mim. Obrigado pela informação.
AdmiralAdama
3

Observe que, na resposta aceita, a primeira opção monitora o arquivo inteiro da outra ramificação (como se git add ...tivesse sido executada) e que a segunda opção resulta apenas na cópia do arquivo, mas não nas alterações (como se você tivesse apenas editou o arquivo manualmente e teve diferenças notáveis).

Git copiar arquivo de outra ramificação sem prepará-lo

Alterações efetuadas (por exemplo 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

Alterações pendentes (não preparadas ou confirmadas):

$ 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
fonte
Eu recebo "o recurso-B não é um arquivo", o nome do ramo vem primeiro, sobre este -> "> diretório / somefile.php" isso pode alterar a codificação do arquivo?
Tiago Oliveira de Freitas