Используя Git и Github, как опустить некоторые коммиты в master?

#git #github #cherry-pick

Вопрос:

Допустим,,

  1. Мы приняли обязательство № 100 для освоения.
  2. Мы хотим, чтобы коммит № 101 в ветке перешел к мастеру
  3. Однако, поскольку потенциально существует некоторая проблема с фиксацией № 100, поэтому мы хотим перейти к фиксации № 99, а затем выбрать вишню № 101 и сделать пиар
  4. Но мы обнаружили, что 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 и для слияния.