Может ли Git отслеживать как ветвь предка, так и его собственную ветку? - PullRequest
0 голосов
/ 11 марта 2020

Извините, если это нубский вопрос, но я искал час + и не могу получить четкий ответ.

Я хотел бы сделать следующее:

  • Извлечь удаленную ветку git checkout origin/feature
  • Сделать локальную ветку на основе этой ветви git checkout -b feature_my_tweak
  • Итак, теперь у меня есть локальная копия feature с именем feature_my_tweak, с которой я могу поиграться с
  • Внести некоторые изменения и commit -m "added my tweak", так что теперь мой локальный feature_my_tweak отличается от feature
  • Теперь выполните git push --set-upstream origin feature_my_tweak to pu sh мою локальную ветку на удаленном сервере
  • Теперь напарник изменяет значение feature на удаленном сервере

На этом этапе я хотел бы иметь возможность git pull и git увидеть, что произошло изменение на feature и перенести его (извлечь / объединить) в мою локальную ветвь feature_my_tweak. Есть ли способ сделать это автоматически? Или мне нужно сделать git merge feature вручную, чтобы получить все изменения из этой ветви в мою локальную ветку feature_my_tweaks? Я думаю, я думал, что есть способ, чтобы одна ветка отслеживала другую.

Другая часть этого заключается в том, что я все еще хотел бы иметь возможность вносить локальные изменения в feature_my_tweaks, и при этом иметь возможность git push и иметь это только pu sh до удаленного origin/feature_my_tweak ветка и не загрязняют ветку origin/feature.

Есть ли способ сделать все это? Из того, что я могу прочитать, кажется, что, если какая-либо ветвь_A отслеживает удаленную ветвь_B, любые нажатия будут go к ветке_B, чего я не хочу.

Надеюсь, это имеет смысл.

1 Ответ

2 голосов
/ 12 марта 2020

TL; DR

Краткая версия ответа сводится к нет, но это не имеет значения, не беспокойтесь об этом и просто делайте это вручную; это просто . Если у вас есть одна конкретная ветка, с которой вы часто делаете это, напишите сценарий или псевдоним Git, чтобы сделать это.

Средний

Чтобы сделать это вручную, для вашей ветви B где вы хотите узнать, есть ли что-то новое на origin/feature, против вашей собственной ветки feature_my_tweaks с восходящим потоком, установленным на origin/feature_my_tweaks, просто запустите:

git rev-list --count --left-right feature_my_tweaks...origin/feature

Это выведет два числа , Число слева - это количество совершенных вами коммитов на feature_my_tweaks, которые не являются частью вашего origin/feature. Число справа - это количество коммитов, которые находятся на вашем origin/feature, которых нет на вашем feature_my_tweaks.

Если второе число не равно нулю, и вы хотите, вы можете запустить git checkout feature_my_tweaks; git rebase origin/feature или git checkout feature_my_tweaks; git merge origin/feature.

Независимо от того, когда и когда использовать git rebase, зависит от вас, но после перебазировки вам нужно будет git push --force origin feature_my_tweaks (или git push --force-with-lease origin feature_my_tweaks), чтобы преодолеть Git на origin, чтобы отменить старые коммиты, которые ваш git rebase отбросил, когда он скопировал ваши коммиты на новые и улучшенные коммиты.

Long

Вероятно, самая большая проблема здесь - терминология. Что для вас означает слово tracking ? Git использует это одно слово как минимум тремя различными способами, 1 , поэтому самое большее одно из них может совпадать с тем, о котором вы думаете. (Возможно, ни одно из них не совпадает точно, в зависимости от того, что вы думаете здесь происходит.)

Независимо от того, какое слово (слова) вы используете, вот правильный способ думать об этом:

  • Что имеет значение совершает . Каждый коммит имеет уникальный идентификатор ha sh. Каждый Git везде - каждый клон этого хранилища - использует , который га sh ID для этого коммита. Если у вас есть коммит с этим ха sh ID, это тот же коммит. Если вы этого не сделаете, у вас нет этого коммита.

  • Имена в Git принимают несколько форм. Каждое имя содержит один га sh ID - только один!

    Три формы, которые вы используете:

    • Имена филиалов: master, develop, feature или feature/one и так далее. Это ваше, делать с вами как хотите. (Вы, вероятно, захотите, чтобы ваше совпадало с именами других людей, хотя бы в разное время.)

    • Имена тегов: v2.1 и так далее. Пока ваши ваши, ваш Git попытается поделиться ими с другими Git хранилищами: если ваш Git видит, что у них есть v2.1, а вы нет, ваш Git может скопировать их на ваш.

    • Имена удаленного слежения: origin/master, origin/feature и т. д. Git называет эти имена веток удаленного отслеживания , и некоторые люди сокращают это до ветви удаленного отслеживания , но они не совсем похожи на имена ветви. Ваши Git подчиняют их другим ветвям Git. У вас есть Git вызов их Git и вы получаете от них новых коммитов . Затем ваш Git обновит ваши имена для удаленного отслеживания, чтобы они соответствовали их именам.

      Имя для удаленного отслеживания создается путем вставки имени remote (в данном случае origin) в перед их ответвлением имени, с именем sh, чтобы держать их на расстоянии. Вот почему ваши origin/master "отслеживают" свои master, обновляемые при каждом запуске git fetch origin. 2


    Все эти имена работают одинаково , Все они имеют длинные формы: refs/heads/master - это полное написание master, например, против refs/remotes/origin/master для origin/master. Вот как Git знает, какое имя какое. Git обычно тогда сокращает имя для отображения для вас, снимая часть refs/heads/ для имен филиалов или refs/remotes/ для имен удаленного отслеживания.

Обратите внимание, что git fetch так же близко, как и к противоположности git push. Может показаться, что это должны быть push и pull, но из-за исторической аварии 3 это push и fetch. Вытягивание означает только: Запустить выборку, затем выполнить вторую команду Git, по умолчанию git merge, чтобы объединиться с восходящим потоком текущей ветви.

Fetch и pu sh очень похожи, но с двумя ключевыми отличиями:

  1. Fetch получает вещей. Вы говорите своему Git: вызвать Git, чей URL вы сохранили под именем origin (или любое другое удаленное имя, которое вы здесь используете). Ваш Git вызывает сервер по этому URL, который должен отвечать как Git хранилище. Затем этот сервер сообщает вам об именах веток и их коммитах, и ваши Git проверяют, есть ли у вас эти коммиты. Если нет, ваш Git запрашивает у своих Git эти коммиты, а их родительские коммиты, если у вас их нет, и родителей родителей, если это необходимо, и так далее. Они дают вам все коммиты, которые у вас есть, а вам нет, что ваш Git должен их выполнить.

    Получив коммиты, git fetch затем обновляет ваши имена для удаленного слежения переименовывая их филиалы.

  2. Pu sh отправляет вещей. Как и раньше, у вас есть Git вызов другого Git по удаленному имени, например origin. Тогда ваш Git дает им коммиты, а не получает коммиты от них. Но здесь все немного по-другому:

    • Коммит (ы), которые ваши Git предложения представляют собой tip коммиты всех веток, которые вы нажимаете. (Если вы просто нажимаете на одну ветку, это всего лишь один коммит.) Если у них нет этих коммитов, ваш Git должен предложить родителям этих коммитов коммитов. (У большинства коммитов есть только один родитель, так что это еще один коммит.) Если у них нет тех , ваш Git должен предложить больше родителей и так далее. В ходе этого процесса ваш Git находит все коммиты, которые необходимы их Git, чтобы получить полную картину tip коммит, который вы отправляете: всю его историю.

      Когда вы собирались, они предложили все свои ветви. Разница в том, что вы нажимаете только те ветви, которые вы указали.

    • После того, как ваш Git отправил любые ваши коммиты, которые они не сделали, что им нужно завершить совет Если коммит (ы) для ветви (ов), которую вы отправляете, ваш Git отправляет вежливый запрос, чтобы они установили свои ветви имена (ей).

      Когда вы выбирали Git установите имена для удаленного слежения . Теперь вы просите их задать имена branch .

Суммировать следующие ключевые моменты:

  • fetch получает (все по умолчанию, если вы не ограничиваете его) фиксирует и разветвляет их и переименовывает их ветви в ваши имена для удаленного слежения
  • pu sh send (один, по умолчанию) 4 commit-tip commit (и его предки, если / когда необходимо), а затем просит их установить их имена ветвей

You может попросить git push попросить их установить имя , отличное от того, которое вы используете для выбора коммитов для отправки. Например:

git push origin test-xyz:new-feature

отправляет коммит-наконечник вашей ветви test-xyz (а также ее родителей и других предков, если / при необходимости), но просит их установить или создать свою ветвь name new-feature.

Итак:

... кажется, что если какая-либо ветвь_A отслеживает удаленную ветвь_B, любые толчки будут go к Branch_B ...

Это совершенно неправильно, по крайней мере по умолчанию. (Существует параметр для push.default, который заставляет осуществить это, хотя.)

Здесь можно узнать намного больше, в частности, что делает этот git rev-list --left-right --count и что означает, что коммиты должны быть «включены» - или, точнее, достижимы из - имени ветви, но в этом ответе у меня как раз заканчивается время и пространство.


1 В частности, файлы могут быть отслежены или не отслежены , некоторые имена имена для удаленного отслеживания , и ветвь с установленным восходящим потоком называется отслеживающим его восходящим. Глагол (в его нынешней форме причастия) становится прилагательным, изменяя имя или файл , в первых двух случаях.

2 Там Есть способы запустить ограниченное git fetch, чтобы не не обновляло все ваши имена для удаленного отслеживания. Использование git pull иногда делает это, например. Я предпочитаю разделять мои git fetch и другие мои команды вместо использования команды git pull fetch-then-run-another- Git -command.

3 Это обычно после извлечения, чтобы захотеть интегрировать то, что вы извлекли , поэтому сначала git fetch была бэкэнд-командой "слесарного дела", не предназначенной для запуска пользователями, и git pull выполнила git fetch, затем git merge. Это было до того, как удаленные существовали как концепция, и, следовательно, до того, как существовали имена для удаленного отслеживания, так что у пользователей не было никаких причин запускать git fetch.

Со временем, Git выросли имена удаленных и отслеживания удаленных, и теперь разница между pull - выборка и объединение - и просто fetch без объединения (или, по крайней мере, без этого пока ) стали полезными и важный. Но имя pull уже использовалось для обозначения извлечения и объединения , отсюда и произошел этот конкретный исторический случай.

4 То есть это значение по умолчанию в Git 2.0 и более поздних версиях. Вы можете изменить его с push.default, а Git версиями старше 2.0 по умолчанию matching.

При использовании matching ваш Git запрашивает у Git названия своих ветвей, совпадения вверх по соответствующим именам ветвей и по умолчанию подталкивает их от соответствующих им имен к их совпадающим именам.

Если вы измените этот параметр на upstream, ваш Git попросит их Git установить их ветвь на основе настройка восходящего потока вашей ветви, что вы и предполагали в своем вопросе.

Современной настройкой по умолчанию является simple, которая требует, чтобы для восходящего потока была установлена ​​ветвь с тем же именем , так что git push на вашем конце сразу же терпит неудачу, если ваш восходящий поток настроен на другое имя их стороны. Однако вы можете легко переопределить это, набрав git push origin <em>branch</em>, что означает то же самое, что и git push origin <em>branch</em>:<em>branch</em>: попросите их Git использовать то же имя ветви, которое вы используете в Git.

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