Как скопировать версию одного файла из одной ветки git в другую?

944

У меня есть две ветви, которые полностью объединены.

Однако после завершения слияния я понимаю, что один файл был испорчен слиянием (кто-то другой сделал автоформат, gah), и было бы проще перейти на новую версию в другой ветке, и затем снова вставьте мое однострочное изменение после переноса в мою ветку.

Так какой же самый простой способ сделать это в git?

madlep
источник
3
Обратите внимание, что в принятом ответе первое решение вносит изменения, а второе - нет. stackoverflow.com/a/56045704/151841
user151841

Ответы:

1675

Запустите это из ветки, где вы хотите, чтобы файл в конечном итоге:

git checkout otherbranch myfile.txt

Общие формулы:

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

Некоторые заметки (из комментариев):

  • Используя хэш коммита, вы можете извлекать файлы из любого коммита
  • Это работает для файлов и каталогов
  • перезаписывает файл myfile.txtиmydir
  • Подстановочные знаки не работают, но относительные пути работают
  • Можно указать несколько путей

альтернатива:

git show commit_id:path/to/file > path/to/file
madlep
источник
13
Да, это так. Но это было целью вопроса.
Ikke
37
Вероятно, очевидно, но вам нужно использовать полное имя файла ... Подстановочные знаки не работают!
Крис Харт
6
хотя .. это также хороший способ: git show commit_id: путь / к / файлу> путь / к / файлу
milushov
14
удаленный: git checkout origin / otherbranch myfile.txt
Роман Ррн Нестеров
6
Использование подстановочных знаков работает, вам просто нужно обернуть их, ''чтобы они не интерпретировались оболочкой.
Виктор Цайковский,
82

Я попал на этот вопрос по аналогичному поиску. В моем случае я искал, чтобы извлечь файл из другой ветви в текущий рабочий каталог, который отличался от исходного местоположения файла. Ответ :

git show TREEISH:path/to/file >path/to/local/file
lkraav
источник
18
Цель «git show» - вывести данные на терминал в читаемом формате, который не гарантирует точное совпадение с содержимым файла. То же самое, что лучше скопировать текстовый документ целиком, а не копировать и вставлять его содержимое в другой документ.
Гонен
Я просто хотел посмотреть его, чтобы сравнить содержимое с текущей веткой (проверьте часть кода). Я хотел бы использовать vim с этим, хотя ... для подсветки синтаксиса и т. Д.
isaaclw
3
Чтобы сравнить содержимое, прежде чем делать заказ, git diff <other branch> <path to file>работает хорошо.
Рэндалл
2
@Gonen: Начиная с git версии 2.21.0, на странице руководства «git show» написано: «Для простых BLOB-объектов он показывает простое содержимое». Я не уверен, означает ли это, что мы всегда хороши. Я с некоторой осторожностью
собираю
52

Как насчет использования команды checkout:

  git diff --stat "$branch"
  git checkout --merge "$branch" "$file"
  git diff --stat "$branch"
RzR
источник
8
Примечание слияние (2-я команда) не может работать, если файл не существует в обеих ветвях
simpleuser
Гектометр У меня нет diffstat. Это конкретная версия инструмента сравнения, потому что я никогда не слышал об этом (и стоит ли переходить на него?): D
dudewad
git diffподдерживает --statаргумент, который в основном делает то же самое, что и diffstat.
Хловдал
Я должен был проверить обе ветви локально, чтобы заставить это работать.
UnitasBrooks
18

1) Убедитесь, что вы находитесь в филиале, где вам нужна копия файла. Например: я хочу файл подветви в мастер, так что вы должны оформить заказ или должен быть в мастереgit checkout master

2) Теперь извлеките конкретный файл, который вы хотите из дочерней ветки в master,

git checkout sub_branch file_path/my_file.ext

Здесь sub_branchозначает, где у вас есть этот файл, а затем имя файла, который нужно скопировать.

Мохидин бен Мухаммед
источник
Очень удобно и хорошо объяснил.
АБК
15

Следуя ответу madlep, вы также можете просто скопировать один каталог из другой ветви с помощью каталога blob.

git checkout other-branch app/**

Что касается вопроса ОП, если вы изменили там только один файл, это будет нормально работать ^ _ ^

6 футов Дан
источник
1
Обратите внимание, что обе ветви должны быть сначала правильно вытянуты или использованы origin/other-branchдля ссылки на ветку репо. Основы, но укусил меня. (ответ отличный - редактирование не требуется)
akauppi
8

Я бы использовал git restore(доступно с git 2.23)

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


Почему это лучше, чем другие варианты?

git checkout otherbranch -- path/to/myfile.txt- Он копирует файл в рабочий каталог, а также в промежуточную область (аналогично тому, как если бы вы копировали этот файл вручную и выполняли git addна нем). git restoreне касается области постановки (если не указано по --stagedжеланию).

git show otherbranch:path/to/myfile.txt > path/to/myfile.txtиспользует стандартное перенаправление оболочки. Если вы используете Powershell, возможно, проблема с заключением текста или вы можете получить поврежденный файл, если он двоичный . С git restoreизменением файлов все делается gitисполняемым файлом.

Еще одним преимуществом является то, что вы можете восстановить всю папку с помощью:

git restore --source otherbranch path/to

или с, git restore --overlay --source otherbranch path/toесли вы хотите избежать удаления файлов. Например, если файлов меньше, otherbranchчем в текущем рабочем каталоге (и эти файлы отслеживаются ) без --overlayопции, они git restoreбудут удалены. Но это хорошее поведение по умолчанию, вы, скорее всего, хотите, чтобы состояние каталога было таким же, как в otherbranch, а не "то же самое, но с дополнительными файлами в моей текущей ветке"

Мариуш Павельски
источник
Хороший ответ. Есть ли git restoreспособ скопировать файл из исходной ветви в новый файл в целевой ветви? С помощью git show я могу сделать это с помощью redirection ( git show otherbranch:path/to/file1.txt > path/to/file2.txt), но я хочу избежать перенаправления оболочки по причинам, которые вы упомянули.
Адмирал Адама
1
@ AdmiralAdama не совсем. И я думаю, что нет большого шанса получить его git restore(но кто знает;)). Эти проблемы с перенаправлением в основном являются проблемой Powershell, но не уверены, что есть какая-либо другая оболочка, которая имеет проблемы с ней. Я обычно возвращаюсь к «git bash» или даже к «cmd», где мне нужно использовать команды « git showс перенаправлением». Или используйте графический интерфейс, например GitExtensions, где вы можете просмотреть дерево файлов коммитов и нажать «Сохранить как» для любого файла.
Мариуш Павельский
Ах я вижу. Я не использую Powershell, так что, возможно, перенаправление оболочки для меня np. Спасибо за информацию.
Адмирал Адама
3

Обратите внимание, что в принятом ответе первая опция выводит весь файл из другой ветки (как git add ...было выполнено), и что вторая опция просто приводит к копированию файла, но не ставит изменения (как если бы вы имели только что отредактировал файл вручную и имел выдающиеся отличия).

Git скопировать файл из другой ветки, не ставя его

Постановочные изменения (например 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

Выдающиеся изменения (не поставленные или не совершенные):

$ 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
источник
Я получаю "feature-B - это не файл", сначала идет имя ветки, об этом -> "> directory / somefile.php", может ли это изменить кодировку файла?
Тьяго Оливейра де Фрейтас