как без проблем выбрать последний патч от другого разработчика - PullRequest
0 голосов
/ 28 августа 2018

Я выбрал один коммит от других разработчиков для какой-то работы.

Через несколько часов один из разработчиков обновил свой патч.

Если я выбираю новый патч cherry, тогда возникают конфликты.

  1. Два добавленных файла: - если новые файлы присутствуют в том же патч
  2. Оба изменены: - один и тот же файл в старом патче и новый патч изменены.

Есть ли способ отменить предыдущий патч или мне нужно вручную разрешить конфликт?

1 Ответ

0 голосов
/ 28 августа 2018

У вас есть два прямых и очевидных варианта:

  • Добавьте второй коммит, который отменяет первый вишневый кир. (Теперь у вас есть исходный снимок, который выглядит так, как будто вы никогда не делали первый выбор вишни.)

  • Удалите первую вишню, то есть измените историю коммитов.

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

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

... <-F  <-G  <-H   <--yourbranch (HEAD)
       \
        I  <-J   <--origin/theirbranch

Затем вы решаете, что по какой-то причине вам нравится их коммит J, поэтому вы запускаете git cherry-pick <hash-of-J> или git cherry-pick theirbranch. копирует эффект коммита J, делая новый коммит. Мы можем назвать этот коммит K, но давайте использовать J', чтобы указать, что это копия J:

...--F--G--H--J'  <-- yourbranch (HEAD)
      \
       I--J   <-- origin/theirbranch

В какой-то момент в будущем они - кем бы они ни были - отказались от своего коммита J в пользу своего нового и улучшенного коммита K, так что после запуска git fetch вы получите:

...--F--G--H--J'  <-- yourbranch (HEAD)
      \
       I--K   <-- origin/theirbranch

(Фиксация J полностью исчезла: новый коммит K указывает непосредственно на I. Это то «переписывание истории», о котором говорят люди.)

На данный момент вы можете переписать свою собственную историю, используя git reset --hard. Конечно, это отбрасывает любую работу, которую вы делаете, но давайте предположим, что вы не сделали никакой новой работы, так что все в порядке:

             J'  [abandoned]
            /
...--F--G--H   <-- yourbranch (HEAD)
      \
       I--K   <-- origin/theirbranch

Теперь вы можете легко выбирать их коммит K, поскольку он не конфликтует с вашей копией J' их оригинала J. В результате вы получите:

             J'  [abandoned]
            /
...--F--G--H--K'  <-- yourbranch (HEAD)
      \
       I--K   <-- origin/theirbranch

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

...--F--G--H--J'-L--M--N--O--P--Q   <-- yourbranch (HEAD)
      \
       I--K   <-- origin/theirbranch

Теперь вам намного сложнее избавиться от J': он встроен в вашу историю, которая простирается от Q до F.

Вы можете использовать интерактивное перебазирование (git rebase -i), чтобы попытаться вырвать J' из своей истории, скопировав коммиты L-M-N-O-P-Q в новые коммиты L'-M'-N'-O'-P'-Q', которые на много похожи на оригиналы, но пропустить J':

             J'-L--M--N--O--P--Q   [abandoned]
            /
...--F--G--H--L'-M'-N'-O'-P'-Q'  <-- yourbranch (HEAD)
      \
       I--K   <-- origin/theirbranch

(Обратите внимание, что это выглядит как повторный сбор вишни. Это потому, что git rebase равен , это повторный сбор вишни!) Но если это слишком болезненно или нежелательно по другим причинам, теперь вы можете сделать новый коммит R, который отменяет действие вашей копии J' их оригинала J, и добавить его в вашу ветку:

...--F--G--H--J'-L--M--N--O--P--Q--R   <-- yourbranch (HEAD)
      \
       I--K   <-- origin/theirbranch

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

git revert <hash-of-J>

Команда git revert сообщает Git: Выясните, что изменилось в данном коммите, и создайте новый коммит, который приведет к отмене этих изменений. Для каждой строки, которую я добавил в какой-либо файл, удалите эту строку из этого файла. Для каждой строки, которую я удалил из некоторого файла, поместите эту строку обратно. Для каждого файла, который я удалил оптом, верните этот файл; для каждого файла, который я создал с нуля, удалите этот файл полностью.

Когда этот процесс завершается, у вас есть моментальный снимок в коммите R, который выглядит так, как будто фиксация J' никогда не происходила. (Если ваши изменения в коммитах L - Q вступают в конфликт с этой попыткой возврата J', вы, как правило, увидите конфликт слияния во время процесса возврата. Обратите внимание, что , если , это так, как правило, вы увидите такие же конфликты, если вы будете использовать интерактивное перебазирование для отмены коммита J' при копировании L -through- Q в новые коммиты.)

...