Лучшая практика для отслеживания восходящего потока в вилке на github

Резюме. Каковы наилучшие методы обработки длинных отслеживаний восходящих репозиториев, где вы хотите поддерживать набор локальных изменений?

Я хочу держать вилку на github актуальной с восходящим потоком, но все же допускаю четкое отслеживание изменений, уникальных для вилки. (для этого обсуждения предположим, что upstream указывает на основной репозиторий проекта и что origin относится к моей вилке репозитория)

Представьте, что у меня есть что-то вроде этого, где я разветвлял репозиторий, когда upstream/master находился в E.

Upstream:
A-B-C-D-E-F


Fork:    
A-B-C-D-E ----- P ------T
         \-L-M-/ \-Q-R-/

После форматирования репозитория я создал две ветки функций (L-M и Q-R), чтобы добавить новые функции, которые мне нужны, и объединить их обратно с моим источником/мастером. Итак, теперь у моей ветки есть улучшения, которые не существуют вверх по течению.

Я обнаружил, что у upstream есть несколько интересных исправлений, поэтому я хочу вернуться к синхронизации с восходящим потоком. Основываясь на большинстве ссылок, которые я нашел (git hub fork), рекомендуемый способ сделать это - объединить upstream/master в ваш источник /master и продолжить путь. Поэтому я бы выдавал команды вроде:

git checkout master
git fetch upstream
git git merge upstream/master
git push

Затем я получаю репозитории, которые выглядят так:

Upstream:
A-B-C-D-E-F


Fork:    
A-B-C-D-E ----- P ------T-F'
         \-L-M-/ \-Q-R-/

Есть несколько проблем, которые я вижу с этим.

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

  • Когда я продвигаюсь вперед и продолжаю делать это, мне становится все труднее узнать, какие изменения у меня есть в моем репозитории, помимо того, что находится в восходящем потоке. Например, я могу отправить некоторые из этих изменений обратно вверх, продолжая добавлять свои собственные уточнения. После нескольких итераций этого, как кто-то смотрит на мой репозиторий, знает, как он отличается от восходящего? (есть ли команда git, чтобы найти эти изменения?)

  • Как и в случае С# 2, как кто-то найдет исправление в восходящем потоке и проверит, содержит ли моя вилка исправление?

Я предполагаю, что корень проблемы заключается в том, что я не могу гарантировать, что мой репозиторий находится в "синхронизации" с восходящим потоком в любой заданной точке, потому что код и хэши не совпадают. Итак, как я могу точно отслеживать изменения и не сойти с ума, чтобы синхронизировать ситуацию?

Примечание. Я подумал о том, что использовать rebase, чтобы сохранить репозиторий в обратном направлении, но у этого есть совершенно другой набор проблем. Например, если кто-либо ссылается на мой репозиторий через подмодули, ветки и т.д., Тогда переписывание истории нарушит их ссылки. Кроме того, я не думаю, что моя история веток сохранится в rebase, поэтому у меня не было бы полного представления обо всех ветвях функций, которые я сделал, и связанной истории.

Как другие люди справляются с этим? Каковы некоторые лучшие практики, над которыми я должен смотреть?


Update:

Основываясь на отзывах от Seth, я создал набор тестовых репозиториев, чтобы показать, о чем я говорю, и как он работает так, как он говорит.

Репозитории:

Они должны более четко показать, как слияние с восходящим потоком выглядит, когда есть локальные изменения.

Ответ 1

Вы ошибаетесь в своем предположении. Вы сказали в своем текстовом примере, что вы используете команду git merge. Если вы действительно имели в виду это, а не git cherry-pick (и для записи git -merge - лучшая практика в ситуации), то вы НЕ получаете F` в своей ветке, вы получаете F. Возможно, изображение:

После извлечения, но до слияния, ваши репозитории выглядят следующим образом:

Upstream:
A-B-C-D-E-F  [master]


Fork:    /-F                  [upstream/master]
A-B-C-D-E ----- P ------T     [master]
         \-L-M-/ \-Q-R-/      [Other branches]

После слияния ваше репо будет выглядеть так:

Fork:    /-F-------------\    [upstream/master]
A-B-C-D-E ----- P ------T-U   [master]
         \-L-M-/ \-Q-R-/      [Other branches]

Новая фиксация "U" в вашем репо будет фиксацией слияния, точно так же, как коммиты "P" и "T".

git cherry-pick создаст "F", как вы указали в своем примере. Не делай этого. git rebase может иногда поддерживать переполнение ветвей git rebase -p, но это не всегда работает. Кроме того, это переписывание публичной истории, что является плохой идеей.

У меня есть документ в git лучших практиках: Commit Часто, Perfect Later, Опубликовать после. Вы можете специально изучить раздел рабочего процесса для дальнейшего вдохновения.