Можно ли программно удалить одну прошлую ревизию из мастера? - PullRequest
0 голосов
/ 08 января 2019

Допустим, у меня есть файл с несколькими ревизиями;

initial commit text
revision one
revision two
revision three
revision four

позднее я хочу удалить некоторые изменения, которые произошли несколько ревизий назад, но сохранить более поздние изменения, например, удалить только изменения, сделанные во второй ревизии;

initial commit text
revision one
revision three
revision four

В настоящее время я вызываю diff для второй ревизии и выполняю поиск и замену мастера вручную, но мне было интересно, есть ли какая-то функциональность, которая позволила бы мне просто взять эту предыдущую ревизию, и Я полагаю, вы примените все, что придет позже?

РЕДАКТИРОВАТЬ: Ничто из этого не работает на основе чего-то, что я не прояснил. «Код» там представляет фактический текст возвращаемого файла, поэтому, когда я предлагаю удалить вторую ревизию, я имею в виду буквальный текст, который говорит «ревизия вторая».

Я пробовал оба инструмента: перебазировать и возвращать, и они отказываются, потому что, добавляя следующие две строки "ревизия три" и "ревизия четыре" ... я продолжаю получать конфликты слияния, когда файл заканчивается чтением;

initial commit text
revision one
<<<<<<< HEAD
revision two
revision three
revision four
=======
>>>>>>> parent of 4ac4327... revision 2

тем временем текст ошибки (этот для возврата, хотя rebase похож)

error: could not revert 4ac4327... revision 2
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

У меня нет проблем с использованием revert или rebase, поскольку это один шаг назад, удаление текста «четвертая редакция», но любая дальнейшая попытка, похоже, не дает мне результата.

Я пытаюсь сделать добавление и принятие, и когда я продолжаю, я получаю

error: no cherry-pick or revert in progress

и я подаю с тремя дополнительными git-сообщениями в файле.

РЕДАКТИРОВАТЬ ВТОРОЕ: Я думаю, что процесс, который я ищу, состоит в том, чтобы проверить на первой ревизии, а затем использовать git cherry-pick ... Я обновлю, как только выясню все это здесь ...

Ответы [ 4 ]

0 голосов
/ 09 января 2019

Проблема решена

Проблема, с которой я столкнулся, была вопросом инструментов, а мое непонимание было связано с различием и слиянием.

Единственное знакомство с diff, которое я имел, - это чтение сообщений коммитов на github / gitlab, которые довольно просты. Из командной строки это был новый опыт для меня, и большинство учебных пособий, которые я обнаружил, были либо простыми тестовыми примерами, которые не выдают ошибок (удаляют последнюю ревизию), либо делали предположение, что пользователь понимает изменения, необходимые в более сложных случаях, таких как Я описывал.

Когда git (rebase, revert или cherry-pick) выполняет действие и выдает ошибку, он (как может быть очевидно для многих, но не для меня) записывает эти ошибки в сам файл. Странные сообщения, с которыми я сталкивался, были самим исправлением, у меня просто не было контекстных знаний. Не помогло то, что инструмент, который я использовал для diff / merge, пытался исправить эти ошибки самым простым способом, а именно, вернуть тот самый коммит, который я пытался удалить. Я до сих пор не знаю, как заставить этот инструмент удалить эти детали, и я прекратил попытки. Я собрал быстрый макрос для vim, и теперь все в порядке.

Итак, проблема была не в git, а в diff. Выполните соответствующее действие git. Когда git выдает ошибку, устраните проблему в самом файле, понимая, что изменения помечены между HEAD и =======, после чего следует завершающий коммит и его sha-хеш. Продолжите операцию git, и она не должна больше выдавать ошибок.

0 голосов
/ 08 января 2019

git revert добавляет новый коммит, который отменяет все, что делал данный коммит. Например, учитывая

a initial commit text
b revision one
c revision two
d revision three
e revision four

(с некоторыми действительно усеченными гипотетическими хэшами слева), вы можете запустить

git revert c

чтобы создать что-то вроде

a initial commit text
b revision one
c revision two
d revision three
e revision four
f revision five

где f эквивалентно тому, что вы делаете сейчас: отмените то, что вы найдете в diff для c.

Это происходит с меньшим риском, чем перебазирование, и безопасно для веток, которыми вы уже поделились.

0 голосов
/ 08 января 2019

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

Предполагаемый способ отменить изменения от одного коммита в git - это git revert <commit> этот коммит. Как объясняет Чепнер, это создаст новый коммит, который перевернет «патч» из целевого коммита. Аргумент <commit> может быть идентификатором фиксации (хеш-значение, уникальное для целевого коммита) или выражением, указывающим на фиксацию (например, HEAD~2 - что означает «вернуться назад 2 из текущего извлеченного коммита»). в вашем примере).

Обратите внимание, что если изменение коммитов 3 или 4 совпадает с изменением от 2, возврат может создать конфликты, которые должны быть разрешены так же, как конфликт слияния. Кроме того, иногда взаимодействие между git revert и коммитом слияния может вызывать проблемы - но это может иметь значение, только если то, что вы отменяете, является слиянием, или, может быть, это коммит, изменения которого уже присутствуют в более позднем слиянии , Если вы выполняете поиск по запросу «отменить слияние» или что-то подобное, вы должны найти существующие ответы, детализирующие эти проблемы (если они возникнут).

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

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

Кроме того, переписывание истории почти всегда рискует создать нарушенные коммиты. Это происходит потому, что вы переписываете коммиты 3 и 4 автоматически, создавая состояния кода, которые никогда не тестировались. Поскольку 4 - это новый «наконечник ветви», возможно, вы его протестируете; но если вы не вернетесь к тесту 3, это может стать историческим перерывом, который может помешать дальнейшему устранению неполадок (например, с git bisect).

Команды типа git rebase -i или git filter-branch могут использоваться для перезаписи истории, но вы должны убедиться, что разбираетесь в вышеперечисленных проблемах, прежде чем решите использовать их таким образом. Я рекомендую прочесть раздел «восстановление из исходной версии» в документации git rebase; это относится к истории, переписывает в целом.

0 голосов
/ 08 января 2019

Вы можете использовать интерактивный rebase для удаления коммита.

Шаги для interactive rebase,

  1. git rebase -i <revision before the one to delete>
  2. В текстовом редакторе удалите нужный коммит
  3. Сохранить и выйти из редактора

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

...