У меня проблема с невозможностью создать «линейную» историю для моей ветки с помощью перебазирования.
Возможно, у меня неправильное представление о том, что можно/нужно сделать, но я работаю вот над чем:
---A---B---E master
|
|---C---D feature
На этом этапе обе ветки (главная и функциональная) синхронизируются со своими удаленными аналогами, а это означает, что эти коммиты есть как в локальном, так и в удаленном репозитории. В этот момент я побежал:
git checkout feature
git pull --rebase origin master
на данный момент, поскольку перебазирование является локальным, а не удаленным, прежде чем я смогу git push
, мне придется git pull
(и я думаю, что в этом и заключается основная проблема).
Итак, спустя git pull
и git push
я ожидал следующего:
---A---B---E---C'---D'---MergeCommit---
Но вместо этого я получаю:
---A---B--------------------C---D---MergeCommit---
| |
|---E---C'---D'--------------|
Примечание. Я не уверен, что
C
иC'
правильно расположены, поскольку у меня нет возможности определить, какой из этих двух был оригиналом, а какой — «копией», но их двое присутствуют.
Вы можете увидеть картинку ниже, чтобы было более понятно.
Я не возражаю против того, чтобы здесь было две «строчки», за неимением лучшего слова.
Я не против иметь «фиксацию слияния». Все это нормально.
Что меня сводит с ума, так это дублирование commit C
и commit D
.
Или даже следующее будет приемлемо:
---A---B-------------------MergeCommit---
| |
|---E---C'---D'-----|
Как мне избавиться от них на любой из «линий». Я продолжаю произносить строки, потому что все это одна ветвь. Я не баловался контролем версий уже несколько лет, я почти уверен, что раньше я этого не делал, и у меня не было дублированных коммитов, вместо этого они представляли собой один линейный график. Я бы винил git pull
из-за сообщения, которое я получаю сейчас и которое я не узнаю, Merge made by the 'ort' strategy.
это кажется мне новым, и я чувствую, что это причина проблем.
Забудьте о git pull
(вас ввели в заблуждение миллионы плохих руководств) и попытайтесь пересмотреть свое понимание Git без использования git pull
. Это приносит больше вреда, чем пользы. Я использовал Git 13 лет, не запуская его git pull
, ни разу. Перебазирование меняет историю ветки. Если его нажать, git push
отказывается работать. Вам нужно использовать git push --force
или, еще лучше, git push --force-with-lease
. Прочтите документацию git push
: git-scm.com/docs/git-push
Если вас устраивают параллельные линии, зачем стремиться к линейной истории? В линейной истории нет никакой добродетели.
@dani-vta Указанный пост и ответ не относятся к этому случаю.
@j6t да, извини, мне следовало расширить свой комментарий. Я поделился этой ссылкой только потому, что увидел некоторую путаницу в том, как ОП думал, что git pull --rebase
работает. Это было не решение, а просто дополнительное разъяснение. @Axiac на самом деле очень хорошо заметил, что не использовал git push --force
среди некоторых неправильных/отсутствующих вещей, сделанных OP.
Я согласен с оценкой ОП о том, что проблема заключалась в регулярном «git pull» удаленной функциональной ветки после «git pull --rebase origin main». Как только произошло перебазирование (из git pull --rebase), удаленная ветка больше не была действительной, и ее следовало принудительно переместить, а не вытащить. Извлечение с помощью слияния после извлечения с помощью rebase — вот что привело к созданию дубликатов коммитов.
Итак, прочитав все это, я понял, что принудительное нажатие после перебазирования - это нормально? Я правильно понял? Для меня «силовое нажатие» всегда представлялось как БОЛЬШОЕ НЕТ-НЕТ. Как тогда решить совместную работу, у всех остальных нет принудительных изменений в своих локальных ветках?
Есть ли у кого-нибудь ответ, как в этом случае получить линейную одну строку?
Привет, неожиданная история коммитов на вашем скриншоте была из ветки master
или ветки feature
? Я был в замешательстве, так как мог запустить git checkout feature
-> git pull --rebase origin master
, а затем смог запустить git push
, чтобы отправить коммиты в свою feature
ветку. История коммитов в моей функциональной ветке будет выглядеть так: A-B-E-C'-D'
. Кажется, вы отправили коммиты с помощью коммита слияния на master
. Был ли пропущен какой-либо шаг для воспроизведения проблемы?
Не могли бы вы попробовать запустить git log feature --oneline
и git log origin/master --oneline
, чтобы дважды проверить историю коммитов и сравнить идентификатор коммита в каждой локальной ветке перед отправкой?
С тех пор я удалил это репо, поэтому не могу точно проверить, но в названии самого последнего коммита написано: «Объединить ветку «feat....», поэтому я предполагаю, что это дерево происходит из «главной ветки».
Попробую повторить еще раз и сделать так, как вы просили.
Вы можете использовать эти git log
команды для ведения записей каждой git
команды, которая может изменить историю коммитов и идентификатор коммитов. Нам было бы полезно понять, как это было воспроизведено.
Итак, мое первоначальное предположение, что это изображение было из основной ветки, было неверным, на самом деле оно было в функциональной ветке. Я воспроизводил эту проблему несколько раз, и она всегда без ошибок создает такой график. У меня есть список шагов для воспроизведения, но он не подходит для «комментария», если хотите, я могу отредактировать вопрос. git log --oneline
указывает на следующий порядок: A--B--C--D--E--C'--D'
после git pull
и git push
.
Это кажется безумием... git pull
полностью разрушает/повреждает цель git rebase
, которую я хочу продвигать/сохранять. Коммиты C'
и D'
по сути будут «пустыми», потому что изменения уже были реализованы C
и D
... извлечение из удаленной функции (чтобы вернуться к ней - как того требует git) после перебазирования - это как если бы я только сделало обычное слияние с мастером, победив всю цель перебазирования
Невозможно перебазировать ветку объекта (т. е. иметь линейную историю) без какого-либо принудительного нажатия позже (ну, я думаю, вы могли бы удалить удаленную ветку и воссоздать ее из новой локальной). Непринудительное нажатие требует, чтобы локальная ветка добавляла только коммиты к кончику удаленной — перебазирование явно перемещает всю ветку.
Я создал репозиторий, похожий на ваш: у меня есть ветка функций «feature»/eabd641, изначально ответвленная от локального «master»/5d2cce8. После git fetch --all
мы видим, что удаленная ветка «master» перешла на новый коммит 82e4b59.
* eabd641 Mon Jul 29 12:01:01 2024 -0400 test 1
| (origin/feature, feature)
| * 82e4b59 Sun May 5 23:15:23 2024 -0400 Fix bug
|/ (origin/master)
* 5d2cce8 Sun May 5 21:54:15 2024 -0400 3/3 challenges
| (HEAD -> master)
* f0994f1 Sun May 5 18:06:48 2024 -0400 2/3 challenges
Если я применю команду OP, используемую
git checkout feature
git pull --rebase origin master
Мое репо теперь выглядит так. Моя ветка функций была переведена на удаленное отслеживание «origin/main»/82e4b59 (мой локальный «master» не был обновлен). Эта функция теперь является линейной, поскольку она находится за пределами (удаленного) главного устройства, но моя ветка удаленного отслеживания «источник/функция» теперь не синхронизирована из-за перебазирования. Коммит «тест 1» существует в локальной и удаленной ветках функций — теперь git pull будет объединяться с локальным и удаленным, что сохранит оба коммита «тест 1» в истории, как видел ОП.
* b1f6f71 Mon Jul 29 12:01:01 2024 -0400 test 1
| (HEAD -> feature)
* 82e4b59 Sun May 5 23:15:23 2024 -0400 Fix bug
| (origin/master, origin/main)
| * eabd641 Mon Jul 29 12:01:01 2024 -0400 test 1
|/ (origin/feature)
* 5d2cce8 Sun May 5 21:54:15 2024 -0400 3/3 challenges
| (master)
* f0994f1 Sun May 5 18:06:48 2024 -0400 2/3 challenges
Теперь я бы git push -f
синхронизировал удаленную ветку «функция» с перебазировкой, затем выполнил сборку и запустил тесты, чтобы код был в порядке, сделал бы еще одну выборку, чтобы проверить, что удаленная «главная» ветка снова не продвинулась, затем git checkout master
, git pull
и git merge feature
(это перемотка вперед — добавьте --no-ff, если вы хотите коммит слияния).
Не уверен, что мне нравится использовать «git pull --rebase origin master», чтобы объединить вытягивание и перебазирование, чтобы перебазировать функцию на кончик удаленного отслеживания «origin/master». Я бы предпочел сначала обновить локальный «мастер», а затем явно перебазировать «функцию» на мой локальный «мастер», а затем git push -f. В любом случае вам все равно придется обновить локальный «мастер».
Я не против обновить локальный мастер, я думал, что pull --rebase
— это просто ярлык. Как обеспечить совместную работу локальных компьютеров товарища по команде, у которых есть другая копия из-за push -f
? Просто попросить их удалить свои копии и вытащить? Что, если у них есть локальные коммиты (еще не отправленные), основанные на предыдущей истории, есть ли способ изменить их?
Вчера был аналогичный вопрос относительно
git pull --rebase
с отличным ответом от @Bert F. Предлагаю вам взглянуть на него, чтобы лучше понять, как на самом деле работает команда. stackoverflow.com/questions/78802778/… К сожалению, хотяgit pull --merge
соответствуетgit fetch
+git merge
,git pull --rebase
не равноgit fetch
+git rebase
.