Если я нахожусь на ветке-A, и я потянул ветвь-B, отличается ли это, если бы я был на ветке-B, и я потянул ветку-A? - PullRequest
0 голосов
/ 26 сентября 2019

Мне просто интересно, как это работает?Если git pull или git merge имеют разницу в зависимости от того, в какой ветке я нахожусь.

В общем,

On branch A: git pull origin B

совпадает с

On branch B: git pull origin A

Ответы [ 2 ]

2 голосов
/ 26 сентября 2019

Они разные.Первый означает

git checkout A
git fetch origin B # to FETCH_HEAD
git merge FETCH_HEAD # to branch A

, в то время как второй эквивалентен

git checkout B
git fetch origin A
git merge FETCH_HEAD # to branch B

. Основное различие заключается в том, какая ветвь объединена с какой.

1 голос
/ 26 сентября 2019

phd-ответ правильный, но я бы пошел дальше: в некоторых случаях они могут быть очень разными.Это действительно зависит от того, что имена A и B идентифицируют в Git по URL-адресу более origin.Если эти имена не связаны с вашими именами A и B, результаты могут быть довольно удивительными.

Как сказал Phd, git pull означает run git fetch, затем выполните вторую команду Git, обычно git merge (но вы можете выбрать, какую команду запускать второй).Шаг выборки использует аргументы, которые вы дали (в данном случае B или A соответственно), чтобы ограничить то, что выбирается.Но: что именно делает извлеченным?

Помните, что Git действительно все о commits .У вас есть некоторый набор коммитов в вашем хранилище.Каждый из этих коммитов имеет уникальный хэш-идентификатор.У их Git тоже есть некоторый набор коммитов в их хранилище.Каждый из их коммитов имеет уникальный хэш-идентификатор.Ваш Git и его Git - и фактически каждый Git во вселенной - согласен на эти хэш-идентификаторы.Так что, если у вас обоих есть один конкретный коммит, вы оба используете одинаковый хеш-идентификатор для этого одного коммитаВот как ваш Git и его Git знают, какие коммиты какие!Ваш Git может узнать, являются ли его коммиты новыми для вас, проверяя хеш-идентификаторы.

Откуда названия ветвей входят в эту картинку?Ответ таков: имена веток помогают любому Git find коммитам.Имя ветки, например A или B, сообщает Git: этот коммит - идентификатор хеша которого хранится под именем ветки - это последний коммит в ветке. Это коммиты сами формируют ветку. name просто позволяет Git найти last .Сами хеш-идентификаторы выглядят случайными.Нам (людям) нужны имена ветвей, потому что мы никак не сможем запомнить какой-либо из хеш-идентификаторов, а Git нужно, чтобы они знали, с чего начать : в конце ветви.

Но имена являются , а не общими. У их Git есть имена ветвей, а у вашего Git - ваши имена веток, и им не нужно никоим образом совпадать. вам очень удобно, если вы делаете свои совпаденияи Git может помочь вам в этом, но это совсем не гарантировано.

Чтобы помочь вам отслеживать подобные вещи, полезно рисовать части графика коммитов.Вы можете использовать графический просмотрщик (gitk, графический интерфейс Git и многие другие);некоторые хороши, а некоторые нет.Или вы можете использовать параметр командной строки git log --graph.Это особенно полезно в сочетании с четырьмя опциями:

git log --all --decorate --graph --oneline

, который пытается составить полезную сводку по всем коммитам по всем ветвям и другим ссылкам (--all), с соединительными линиями от дочерних коммитов до их родителей (--graph) при использовании однострочного формата (--oneline) и маркировке каждого коммита, имеющего имя ветви или тега, указывающего на него этими именами ветвей и / или тегов (--decorate).

Мы также можем сделать этот вид рисования графиков вручную, и это часто довольно полезно.Предположим, что в вашем хранилище есть что-то похожее на это:

...--F--G------H   <-- branch-A
         \
          I--J   <-- branch-B

Одиночные заглавные буквы здесь обозначают реальные хеш-идентификаторы коммитов (которые длинные, некрасивые и выглядят случайными);git log --all --decorate --oneline --graph напечатает фактические хэш-идентификаторы, но сокращенно, и попытается нарисовать это по вертикали вместо этого: например,

*   b9124f1 (Branch-A) subject line from commit H
| * a123456 (Branch-B) subject line from commit J
| * 02ca132 subject line from commit I
|/
* e310f45 subject line from commit G
* 7720dd4 subject line from commit F

.

Теперь предположим, что имя branch-A на other Git, тот, который ваш Git вызывает origin, идентифицирует такой же коммит как ваш branch-A.Предположим далее, что другой Git branch-B также идентифицирует тот же коммит, что и ваш branch-B.Тогда:

git fetch origin

имеет вашGit вызывает их Git, находит все их ветви, копирует любые новые коммиты, которые у вас есть, которые вы не делаете, в свой собственный Git, а затем создаете или обновляете серию origin/* имен, беря их имена ипереименовывая их.Поэтому после этой операции git fetch мы можем нарисовать ваше содержимое Git следующим образом:

...--F--G------H   <-- branch-A, origin/branch-A
         \
          I--J   <-- branch-B, origin/branch-B

То есть вы не получили никаких новых коммитов (у вас обоих был одинаковый набор коммитов) но теперь ваш Git помнит, что их branch-A идентифицирует коммит H, точно так же как ваш, и их branch-B идентифицирует коммит J точно так же, как у вас.

Но что, если это не , что идентифицируют их ветви?Что если их branch-A идентифицирует коммит J, а их branch-B идентифицирует коммит F?Тогда у вас будет:

...--F   <-- origin/branch-B
      \
       G------H   <-- branch-A
        \
         I--J   <-- branch-B, origin/branch-A

Или у них могут быть новые коммиты, которых у вас нет.Возможно их branch-A указывает на новый коммит, чей родитель H;давайте назовем этот коммит K:

                 K   <-- origin/branch-A
                /
...--F--G------H   <-- branch-A
         \
          I--J   <-- branch-B, origin/branch-B

Это все возможности.Без фактической проверки вашего хранилища после использования git fetch для получения каких-либо новых коммитов из их хранилища и обновления ваших различных origin/* имен, мы не можем точно знать, что произойдет.

Но если в этом состоянии 1 мы идем дальше и запускаем git pull, git pull сначала запустит git fetch и получит новые коммиты (если они есть), а затем запустит git merge.Этот git merge попытается объединить новые коммиты, если таковые имеются, или существующие коммиты, если они у нас уже были, с любой веткой, которую мы проверили прямо сейчас.По сути, мы спросим другого Git: Какой хэш-идентификатор коммита идентифицирует ваш branch-A или branch-B? Мы получим любые новые коммиты, которые нам нужны, и тогда мы git mergeсовершить их branch-A или branch-B идентифицированы.Что именно это будет делать?Если мы не знаем что их branch-A или branch-B идентифицирует, прежде чем мы спросим их, что он идентифицирует, нет никакого способа узнать, что это будет делать.

В некоторых (хорошо контролируемых) ситуациях вы можете быть совершенно уверены в том, что произойдет: вы знаете, кому разрешено делать что-либо с репозиторием Git по адресу origin, так что вы в любом случае можете предсказать, по крайней мере с некоторой точностью, что их branch-A или branch-B будет означать.В этом случае git pull не так уж и небезопасно.Я все еще предпочитаю запускать git fetch отдельно, но вы вполне можете использовать git pull.Просто помните, что git pull означает run git fetch, а затем выполните вторую команду Git для любого извлечения, принесенного .Если эта вторая команда git merge, знайте, что делает git merge.Если эта вторая команда git rebase, знайте, что делает git rebase.


1 Незнание здесь просто означает не зная .В общем, невозможно заранее знать, что именно сделает git fetch.Поэтому каждый раз, когда вы используете git pull, вы рискуете!Я предпочитаю сначала запустить git fetch, затем посмотреть, что извлекла , и только , а затем решить, уместно ли запустить git merge.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...