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

Я пытаюсь получить содержимое файла из другой ветки.
Я делаю следующее:

git checkout branchB some_specific_file.cc  

Текущая ветвь остается неизменной. Я подозреваю, что причина в том, что хотя я сделал git pull Я никогда не проверял branchB на местном уровне.
Есть ли способ для этой команды работать, если я только что сделал pull в репо, но никогда не проверял другую ветку?
Есть ли что-то эквивалентное:

git pull  
git checkout branchB  
git checkout branchA  
git checkout branchB some_specific_file.cc 

без необходимости переключаться на ветви, чтобы последняя команда работала?

2 ответа

Решение

TL;DR

Я думаю, что вы хотите, это:

$ git fetch
$ git checkout origin/branchB -- some_specific_file.cc

Фон

Основная ошибка, которую вы совершаете, заключается в том, что вы думаете, что ветви что-то значат.:-) Вернее, название ветви имеет какое-то глобальное значение, но это не так!

git pull команда предназначена для удобства: сначала она запускается git fetchЗатем он запускает вторую команду Git. Вторая команда по умолчанию обычно git merge, но (а) вы можете изменить это и (б) есть некоторые угловые случаи. Причина того, что это предположительно (но не совсем) удобно, состоит в том, что git fetch только получает новые коммиты. Это не влияет ни на одну из ваших веток (которые принадлежат вам, они не относятся к каким-либо удаленным origin!).

Как правило, после того, как вы получили новые коммиты от некоторого удаленного, как origin, вы захотите включить (некоторые из) этих коммитов в (некоторые) ваши собственные ветки. Для этого вам понадобится вторая команда Git, например git merge или же git rebase, Здесь есть много небольших проблем, таких как:

  • Как вы знаете, следует ли объединить, перебазировать или сделать что-то еще полностью?
  • Что если вы хотите работать более чем в одной из своих ветвей?

git pull удобство команда отбрасывает все это в сторону и уверяет вас, что независимо от того, что git fetch сделал, вы на 100% уверены, что немедленное git xxx- вы заполняете xxx часть, прежде чем вы получите - правильный ответ! Если это не так - что на самом деле, по моему опыту, оказывается очень часто, - тогда git pull это неправильная команда.

Что ты делаешь выше

Ваша последовательность этих двух команд выше:

git pull
git checkout branchB

будет, если у вас еще нет branchB, создайте для себя новое (локальное) название филиала branchB, указывая на тот же коммит, что и ваше существующее имя удаленного отслеживания origin/branchB, Затем:

git checkout branchA

возвращает вас к вашей (предположительно существующей) ветке A, о которой мы расскажем подробнее. Последняя команда:

git checkout branchB -- some_specific_file.cc

затем извлекает этот конкретный файл из коммита, идентифицируемого по имени branchB, (Я добавил -- здесь - это хорошая идея использовать его по рефлексу, если имя файла напоминает git checkout название варианта или филиала; some_specific_file.cc не будет, так что в любом случае это безопасно.)

git pull = git fetch + git merge

git fetch на шаге ваш Git вызывает другой Git, обычно по URL, который вы сохранили под именем origin, Их Git перечисляет имена их ветвей, и идентификаторы хеша коммитов идут вместе с этими именами веток. Затем ваш Git гарантирует, что у вас есть эти коммиты, и, как только вы это сделаете, настраивает origin/*имена, чтобызапомнить эти хэш-идентификаторы.

origin/*имена - это то, что я называюименами удаленного слежения; Git называет их именами веток для удаленного отслеживания. Они помнят для вас в вашем собственном репозитории Git, где были имена веток пульта дистанционного управления, в последний раз, когда ваш Git говорил со своим Git.

Следовательно, так какgit pullработаетgit fetchэто имеет побочный эффект обновления имен удаленного отслеживания. Но есть проблема: git pull в его стремлении быть удобным, ограничивает набор имен, которые git fetchвыбирает.

Обычноgit fetchизвлекаетвсе их имена веток, обновляя все ваши соответствующие имена для удаленного отслеживания. Когда бегать из git pullТем не менее, Git смотрит на так называемуювосходящую настройку вашей текущей ветки. Как правило, вверх по течению masterявляетсяorigin/master, вверх по течению branchA является origin/branchA, и так далее. Это ваши имена для их филиалов. когда git pull работает git fetch, это говорит: только обновите это одно имя удаленного отслеживания.

Что это означает, в конце концов, чтоgit pullпока не включен branchBне будет обновлять ваш origin/branchBи это (в конце концов) большая проблема. Вам нужно будет изменить порядок команд: проверьтеbranchB Сначала потяни. (Или лучшеизбегатьgit pull, но подождите.)

Создание (локальной) ветки

git checkoutКоманда переключит вас на какую-то существующую ветку, которая у вас уже есть:

git checkout master

например, переключит вас наmaster что вы, вероятно, уже есть. Но если у вас его еще нет, git checkout будет сканировать ваш origin/* имена - имена удаленного отслеживания (не точно ветвь) - чтобы увидеть, есть ли одно, которое соответствует после удаления origin/ часть.

Если это так, ваш Git создаст новое имя локальной ветви, которое имеет origin/ версия сама по себе как его "вверх по течению".

git merge работает всегда и только на текущей ветке

Последний шаг git pull нормально бегать git merge, Если вы запускаете:

git checkout branchB
git pull

это означает, что Git должен:

  • проверить свой существующий branchBили создайте его при необходимости из origin/branchB;
  • получить и обновить origin/branchB (только);
  • бежать git merge обновить текущую ветку -branchB- используя его вверх по течению, origin/branchB, который git fetch только что обновил.

Шаг слияния сделает ваш локальный филиал branchB получить обновление.

Итак, в общем, вы должны git checkout branchB перед вами git pull чтобы убедиться, что origin/branchB является (единственным) именем удаленного слежения, которое fetch обновления, а затем свой собственный местный branchB также обновляется.

Тебе это не нужно

Но вам не нужно ничего этого для вашей задачи. Если вы просто бежите git fetch, который обновляет все ваши origin/* имена, а затем использовать origin/branchB определить коммит, который содержит версию some_specific_file.cc что хочешь, то хорошо. Отсюда и окончательный набор команд, которые я предлагаю наверху.

Вы можете запустить git fetch синхронизировать удаленные ветви и затем извлекать файл непосредственно из origin/branchB

git checkout origin/branchB some_specific_file.cc 

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

git checkout target_branch -- file.cpp

Это действительно помогает мне, избавляет от необходимости проверять всю ветку и затем перестраивать проект. Просто проверьте нужный мне файл. Нестандартной перестройки избегают. Большое спасибо!

Другие вопросы по тегам