Как вы работаете с публичным хранилищем, которое уже было перебазировано? - PullRequest
4 голосов
/ 09 декабря 2011

Этот вопрос, вероятно, задавался ранее, но у меня немало времени на его поиск.

Очень часто опытные git пользователи скажут: "не rebase репозитории, которые ужебыл публично разоблачен!и это правильно.Но я не вижу никакой информации, касающейся последствий.Я знаю, что это ситуация, в которую мы не должны попадать, но что мы делаем, когда это происходит?

Original: A--B--C--D--E--F
My Repo:  A--B--C--D
                    \
                     X--Y--Z
Rebased:  A--B
              \
               L--M--N--O

Итак, я fetch, это должно быть довольно просто, верно?И ... тогда что происходит?Если я сделаю `pull --rebase, то в какой-то момент произойдет сбой, потому что C--D отсутствует.С какими ошибками я действительно столкнусь и как я могу это исправить?

Ответы [ 2 ]

3 голосов
/ 06 декабря 2013

Вы должны сделать (как в " Как мне восстановить / повторно синхронизировать после того, как кто-то отправит ребаз или сброс в опубликованную ветку? "):

git checkout yourBranch
git branch old-upstreamBranch D # BEFORE fetching!

           E--F (origin/upstreamBranch)
          /
A--B--C--D (old-upstreamBranch)
          \
           X--Y--Z (yourBranch)


git fetch


     L--M--N--O (origin/upstreamBranch)
    /
A--B--C--D (old-upstreamBranch)
          \
           X--Y--Z (yourBranch)

На данный момент вы не можете просто перебазировать свою ветку поверх переписанной upstreamBranch: это привело бы к появлению C и D, которые были явно оставлены в стороне, когда upstreamBranch было переписано.

Вам нужно перебазировать просто yourBranch, а не коммиты до него.
Вот почему вы ставите тег old-upstreamBranch перед извлечением:

git rebase --onto origin/upstreamBranch old-upstreamBranch yourBranch

                X--Y--Z (yourBranch)
               /
     L--M--N--O (origin/upstreamBranch)
    /
A--B--C--D (old-upstreamBranch)



git branch -D old-upstreamBranch 

                X--Y--Z (yourBranch)
               /
     L--M--N--O (origin/upstreamBranch)
    /
A--B

Но: С Git 2.0 все, что вам нужно будет сделать, это :

fork_point=$(git merge-base --fork-point origin/upstreamBranch yourBranch)
# return D
git rebase --onto origin/upstreamBranch $fork_point yourBranch

Больше не нужно "делать ветку до выборки!

Если вы поймете проблему после git fetch, вы все равно сможете красиво перебазировать свою ветку поверх переписанной вышестоящей ветки.


Поскольку commit ad8261d из Джон Кепинг (johnkeeping) , git rebase может использовать эту же новую опцию --fork-point.

3 голосов
/ 09 декабря 2011

В справочной странице git-rebase есть раздел под названием «ВОССТАНОВЛЕНИЕ ОТ РЕБАЗЫ UPSTREAM», который достаточно хорошо описывает это.

Получение

Для вашего конкретного случая давайте разберемся, что происходит.Если вы просто выбираете, все, что вам нужно, это обновлять ветку удаленного отслеживания.Это по-прежнему работает нормально - оно выдаст вам предупреждение , хотя:

From <url>:
 + abc123...def456 master    -> origin/master  (forced update)

Потянув

Поток, будь то обычный (слияние) или перебазирование, вызывает выборку изнутри,Так что , если вы еще не получили, вы увидите предупреждение «принудительное обновление» .Если вы уже загрузили, предупреждение о принудительном обновлении было дано раньше, и сейчас нет принудительного обновления, чтобы предупредить.Вы также можете пропустить предупреждение о принудительном обновлении, если после него будет большой отчет о разнице.После выборки git-pull затем вызывает merge или rebase в соответствии с запросом.Вот где это становится действительно страшно.Что касается Git сейчас, коммиты C и D теперь просто локальные коммиты.Неважно, что в один прекрасный момент они были опубликованы.Таким образом, Git будет сливаться / перебазироваться, как обычно.

Слияние:

- A - B - L - M - N - O (origin/master)
   \                   \
    C - D - X - Y - Z - Q (master)

Ребаз:

 - A - B - L - M - N - O (origin/master) - C' - D' - X' - Y' - Z' (master)

Теперь любой из них может очень хорошо работатьв конфликты, если удаление коммитов C и D делает последующие коммиты другими. Конфликты слияния - это единственные другие ошибки, которые вы заметите. Но если они были изолированными изменениями, то все идет "хорошо".Если пользователь не замечает этого, он может затем протолкнуть эту историю, и, таким образом, вновь ввести удаленные коммиты!Иногда это может быть относительно мягким.Может быть, L на самом деле C с опечаткой, зафиксированной в сообщении фиксации, и MNO идентичны DEF, только с разными родителями.Так что повторное введение C и D не сделало бы ничего, кроме беспорядка в истории.Но, может быть, это ужасно опасно: возможно, удаление C исправило какую-то ужасную ошибку, и она только что была повторно введена.

Как избежать проблемы

И именно поэтому это действительно плохая идеяпереписать опубликованную историю.В лучшем случае заканчиваются дублирующиеся коммиты, а в худшем - пользователь неосознанно нарушает все.Поэтому, если это произойдет, самое первое, что вам нужно сделать, это сказать всем и указать им, как восстановиться.Следующее - внимательно следить за всем, что впоследствии публикуется, чтобы убедиться, что оно не вводит старые коммиты.Если вы находитесь на другой стороне этого, извлекая из публичного репо, надеюсь, вы достаточно доверяете сопровождающим, чтобы никогда не перебазировать стабильную ветку или сообщить вам, если они это сделают.Если вы им не доверяете, то рекомендуется извлекать, а затем объединять / перебазировать, а не извлекать данные, чтобы вы могли заметить сообщение «принудительное обновление» и действовать очень осторожно.

Локальное восстановление

Детали того, как восстановить, различаются;Я рекомендую вышеупомянутую справочную страницу.Трудно точно сказать, что вам нужно делать - это зависит от того, был ли C переписан в L (и, возможно, D в M) или это совершенно новые коммиты, и от того, хотите ли вы перебазировать или объединить.Если вы просто хотите перебазировать, достаточно перебазировать XYZ на O.Если вы хотите объединить, вы должны изменить XYZ на B или M, а затем объединить O.

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