Мне нужно всплыть и удалить «средний» коммит в моей основной ветке. Как мне это сделать? - PullRequest
83 голосов
/ 22 апреля 2011

Например, в следующей основной ветке мне нужно удалить только коммит af5c7bf16e6f04321f966b4231371b21475bc4da, который является вторым по причине предыдущей перебазировки:

commit 60b413512e616997c8b929012cf9ca56bf5c9113
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Tue Apr 12 23:50:15 2011 +0200

    add generic config/initializers/omniauth.example.rb

commit af5c7bf16e6f04321f966b4231371b21475bc4da
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Fri Apr 22 00:15:50 2011 +0200

    show github user info if logged

commit e6523efada4d75084e81971c4dc2aec621d45530
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Fri Apr 22 17:20:48 2011 +0200

    add multiple .container at blueprint layout

commit 414ceffc40ea4ac36ca68e6dd0a9ee97e73dee22
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Thu Apr 21 19:55:57 2011 +0200

    add %h1 Fantastic Logo + .right for 'Sign in with Github'

Мне нужно сохранить

  • Первый совершить 60b413512e616997c8b929012cf9ca56bf5c9113,

"выбрасывая" только второй фиксации af5c7bf16e6f04321f966b4231371b21475bc4da

Как я могу это сделать?Заранее спасибо Лука

Ответы [ 3 ]

89 голосов
/ 22 апреля 2011

Rebase или revert являются опциями.Rebase на самом деле удалит коммит из истории, так что похоже, что второй коммит никогда не существовал.Это будет проблемой, если вы выдвинули основную ветку в другие репозитории.Если в этом случае вы попытаетесь выполнить толчок после перебазирования, git выдаст вам отклонить ошибку без ускоренного слияния .

Возврат является правильным решением, когда ветвь была передана другимРЕПО.git revert af5c7bf16 сделает новый коммит, который просто отменяет изменения, внесенные af5c7bf16.Таким образом, история не переписывается, вы сохраняете четкую запись об ошибке, и другие репозитории принимают толчок.

Вот хороший способ стереть: git rebase -i <commit>^ Это приведет вас к фиксации непосредственно передтот, который вы хотите удалить.Интерактивный редактор покажет вам список всех коммитов на тот момент.Вы можете выбрать, сквош и т. Д. В этом случае удалить строку для коммита, который вы хотите стереть, и сохранить файл.Rebase закончит свою работу.

29 голосов
/ 22 апреля 2011

Если параметр перебазирования является опцией, вы можете перебазировать и просто отбросить ее:

$ git rebase -i 414ceffc^

Если перебазировка не является опцией, вы можете просто отменить ее:

$ git revert af5c7bf16
24 голосов
/ 04 августа 2017

Несмотря на всю достоверность полученных здесь оригинальных ответов, я не нашел их, чтобы удовлетворительно ответить на вопрос. Если вы оказались в ситуации, когда вам нужно удалить коммит или коллекцию коммитов из середины истории, я предлагаю следующее:

  • Создайте новую ветвь с заголовка той, которая содержит все коммиты, и переключитесь на нее.
  • Верните новую ветку обратно в точку, с которой вы хотите начать новую базу.
  • Затем (вот ключевой момент) cherry pick последующие коммиты, которые вы на самом деле хотите применить после этого, от исходной ветви к новой, и пропускайте коммиты, которые вам больше не нужны ( то есть те, которые вы удаляете).
  • При желании переименуйте исходную ветку во что-то, указывающее, что это старый код, а затем переименуйте вашу новую ветвь так, как она называлась оригинальной.
  • Наконец, внесите изменения в удаленное репо (если оно используется). Вы, вероятно, должны будете использовать «принудительный толчок». Если у ваших соавторов есть проблемы с извлечением ревизий, им может быть проще просто снова клонировать репо из удаленного источника. Так или иначе, вы, вероятно, захотите поговорить с ними, если вы все равно вырываете коммиты из середины своей истории!

Вот информация о Cherry Picking: Что означает "выбор вишни" при помощи git?

Вот кое-что о том, как сделать это с помощью Tortoise Git (как я только что сделал). Определенно проще использовать утилиту графического интерфейса для таких операций! Cherry pick с использованием TortoiseGit

...