Получить содержимое файла из другой ветки, не проверяя его
Я пытаюсь получить содержимое файла из другой ветки.
Я делаю следующее:
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
Это действительно помогает мне, избавляет от необходимости проверять всю ветку и затем перестраивать проект. Просто проверьте нужный мне файл. Нестандартной перестройки избегают. Большое спасибо!