#git #github #cherry-pick
Вопрос:
Допустим,,
- Мы приняли обязательство № 100 для освоения.
- Мы хотим, чтобы коммит № 101 в ветке перешел к мастеру
- Однако, поскольку потенциально существует некоторая проблема с фиксацией № 100, поэтому мы хотим перейти к фиксации № 99, а затем выбрать вишню № 101 и сделать пиар
- Но мы обнаружили, что PR (запрос на вытягивание) не содержит «обратного» коммита #100.
Как это может произойти?
Точные шаги, которые мы сделали:
git checkout 3f6231 # the commit ID for commit #99
git checkout -b some_new_branch
git cherry-pick 523c62 # the commit ID for commit #101
git push --set-upstream origin some_new_branch
и создал пиар. Итак, теперь мы ожидаем, что в PR будут внесены изменения в коммит № 101, но изменили коммит № 100 (потому что мы не выбрали его). Однако мы видели, что PR содержит только изменения для фиксации № 101, без обратного #100. Если мы объединим его в master, то, как и ожидалось, мы все равно увидим изменения фиксации #100. Как мы можем опустить коммит #100? (или в реальной жизни это может быть серия из них, таких как #100a, #100b, #100c, и мы хотели бы пропустить их все и перейти непосредственно к #101).
Комментарии:
1. Вы так и не удалили коммит #100. Вот
git revert
для чего это нужно.2. нам нужно удалить коммит #100? Что, если нам нужно посмотреть на то, что мы сделали при совершении #100 позже-это все еще в истории? Также… Я подумал, что шаги в моем вопросе очень логично «строят» фиксацию № 99, а затем выбирают вишню № 101 и, следовательно, пропускают #100 и должны работать… если нет, то почему бы и нет?
3. Если вы случайно включили фиксацию #100 в master и хотите избавиться от нее, вам придется ее отменить. Вы не можете «объединить» его, так как это не приведет к удалению изменений, добавленных ранее. Вы могли бы выполнить жесткий сброс
master
, чтобы зафиксировать #99 и принудительно нажать его, но это испортит все локальные репозитории.4. При слиянии git посмотрит, что находится в master (коммиты 99, 100 и 101) и что находится в вашей временной ветке (коммиты 99 и 101), а затем попытается найти их объединение. Это коммиты 99, 100 и 101 — точно так же, как на master, так что ничего не изменится.
5. Вы переназначили ветку PR на master?
Ответ №1:
Если ветка защищена, вам нужно вернуть ее и создать PR только для этого
git checkout -b correcting master
git revert HEAD # revert last revision
git push origin @ # push the branch to origin
Создайте один MR и объедините.
То, что вы хотели увидеть , увидеть, как редакция 100 улетает от мастера с вашей работы some_new_branch
, не работает, потому что редакция 100 уже является частью мастера, и слияние не удалит то, что сделала редакция 100 (это фактически нарушит суть слияния). Вы можете либо вернуться (как я делаю здесь), либо вернуть ветвь (что технически возможно в git, но это не самый простой/чистый подход к общим ветвям, поэтому это запрещено делать в защищенных ветвях в gh).:
git push -f origin 3f6231:master
Если ветвь защищена, это, вероятно, приведет к сбою. Я пишу это только ради документации. Это переписывание истории для филиала, и это имеет последствия, которые выходят за рамки вопроса.
Другим подходом было бы сделать вашу ветвь новым мастером…. но, опять же, это переписывает историю
git push -f origin some_new_branch:master
# also make it like that locally
git branch -f master some_new_branch
Другим способом было бы вернуть 100 поверх (исходного) 101 в ветке функций. Это может сработать нормально.
Комментарии:
1. итак, если была фиксация #100a, #100b, #100c, то нам нужно вернуть #100c, #100b, #100a, а затем выбрать вишню #101?
2. Похоже на то.
3. для полноты картины, что, если у нас есть фиксация #100a, #100b, #100c, а затем #101, #102, #103 в master на github, и теперь мы хотим получить #104 в ветке, но не #100a, #100b, #100c?
4. кроме того, если фиксация #100a, #100b, #100c были объединены в качестве PR в фиксации ID 3af1234, то разве этого недостаточно просто
git revert 3af1234
?5. возврат слияния? Конечно, этого должно быть достаточно. Единственное, что нужно сделать, чтобы отменить коммиты слияния, вам нужно указать родителя, которого вы не хотите возвращать, что предусмотрено
-m
. Проверятьgit help revert
Ответ №2:
нам нужно удалить коммит #100? Что, если нам нужно будет посмотреть, что мы сделали при совершении #100 позже
Поскольку фиксация для удаления уже включена master
, не рекомендуется удалять ее из истории способом, который вы описали. Пожалуйста, используйте git revert
для отмены фиксации #100, сделав другую фиксацию, которая отменяет изменения.
git revert <sha>
«обратная сторона» фиксации #100
Это действительно даст вам обратную сторону № 100, а не его несуществование.
После возврата #100 и фиксация, которая возвращает #100, возможно, #102, все еще будут в истории, так что вы можете просмотреть их в любое время.
Сброс, восстановление и возврат
Возможно, вы даже хотите, чтобы коммит возврата был #101 / сразу после #100 в истории, и вы хотите, чтобы текущий #101 был #102 / после коммита возврата.
git revert HEAD~
git rebase -i master
# Reorder the commits
Ответ №3:
Вы не говорите, является ли это публичным репо, или размер, или команда, которая его использует, или что-то еще. Вы можете локально наложить цепь на мастера и подтолкнуть ее вверх, что-то вроде:
git checkout 3f6231 # the commit you said you wanted
git checkout -B master
git push -f
вам, вероятно, потребуется отключить любую защиту филиалов, пока вы это делаете. Возможно, было бы неплохо добавить ветку «master_copy» или что-то в этом роде на случай, если вы что-то напутаете. Если вы небольшая команда и репо является частным, то этот метод может сработать — вам нужно будет сообщить другим членам команды, чтобы убедиться, что их мастер был в курсе, что-то вроде:
git fetch
git checkout origin/master
git branch -D master
git checkout master
запускайте локально. Если это публичное репо, в нем много пользователей и/или что — то изменилось (люди добавили коммиты к старому мастеру), то забудьте об этом-последнее, если, возможно, вы не захотите вручную выбрать вишню.
Вы на самом деле не говорите, почему вы не хотите совершать 100. Если это ошибка или вводит ошибки и т. Д., То, как сказано в другом месте, лучше всего использовать git revert. Если он содержит что-то, чего не должно быть (большой файл/пароль/файл, на который у вас нет прав и т. Д.), То, возможно, более целесообразно что-то вроде BFG.
(Отредактировано, так как я забыл «git fetch» во второй последовательности)
Комментарии:
1. «потенциально существует какая-то проблема с фиксацией #100» (имеется в виду ошибка или что-то в этом роде)
Ответ №4:
Я думаю, что добавлю к ответу вопрос: почему предложенный в вопросе метод не работает?
Ответ таков: когда мы делаем пиар для слияния, git обеспокоен изменениями. То
и то -
. git не беспокоится о «состоянии» репо. Повторите еще раз: git обеспокоен изменениями, а не состоянием.
Поэтому, если мы git checkout
определим идентификатор фиксации, а затем выберем несколько фиксаций, git
мы подумаем об этих изменениях и, следовательно, у нас будет возможность объединить эти изменения. Коммиты, которые мы пропустили между ними, git
не видят никаких записей об этих изменениях в этом PR, поэтому он ничего не сделает. Чтобы git увидел эти изменения, нам нужно, чтобы git revert
эти коммиты, желательно в обратном порядке, записывали изменения, чтобы они вошли в этот PR и для слияния.