Почему пропущенные коммиты из git rebase вызывают конфликты слияния? - PullRequest
0 голосов
/ 31 января 2019

Моя проблема

Я работаю над git-репо.Перед публикацией своих изменений я хотел бы удалить некоторые коммиты - a023b43, 315424b и 7b51754 - поскольку они не отражают каких-либо значимых изменений.Единственные важные моменты времени - это первый (70f72ca) и последний (6937ddd) коммит.

Что я пробовал

git rebase -i 4c802c1

Я выбрал:

pick 70f72ca Remove repetitions from Makefile
d a023b43 Separate target for image conversion
d 315424b Remove image conversion (#1)
d 7b51754 Fix Makefile
pick 6937ddd CV 2019.01

Конечная цель - создать журнал git, который выглядит следующим образом:

6937ddd CV 2019.01
4c802c1 Initial commit

Что не сработало

Auto-merging src/Adam_Matan.tex
CONFLICT (content): Merge conflict in src/Adam_Matan.tex
error: could not apply 6937ddd... CV 2019.01

Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

Could not apply 6937ddd... CV 2019.01

Насколько я понимаю, два коммита - это просто снимкимоего рабочего каталога.Я хочу получить два снимка - исходный коммит и CV 2019.01.Я не хочу ни объединять, ни объединять их.Почему я получаю сообщение о конфликте слияния?

Мой вопрос

Как удалить все промежуточные коммиты из ветви и оставить только первый и последний коммит?

Обновить

Сквош также создает конфликты слияния:

git rebase -i 4c802c1
Auto-merging Makefile
CONFLICT (content): Merge conflict in Makefile
error: could not apply 315424b... Remove image conversion (#1)

Ответы [ 3 ]

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

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

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

Представьте, что у вас есть какой-то файл, и в его первоначальной редакции он содержит одну строку с содержимым one.Представьте, что в следующем коммите вы измените one на two.В последующем коммите two до three.Затем three до four и, наконец, four до five.Итак, теперь у вас есть пять коммитов, каждый меняет эту строку.

Представьте, что в каждом коммите вы давали ему сообщение, указывающее на изменение содержимого, и что магическим образом идентификатор фиксации (хэш) также отражал содержимое.Запуск rebase -i --root даст вам такой сценарий:

pick 1111111 add one
pick 2222222 change one to two
pick 3333333 change two to three
pick 4444444 change three to four
pick 5555555 change four to five

Другими словами, первый коммит выбирает изменение с нуля до one.Вторая команда выберет изменение с one до two и т. Д., Пока последняя инструкция не выберет изменение с four до five.

Если вы удалите некоторые из этих строк, дающие вам:

pick 1111111 add one
pick 5555555 change four to five

У вас будет два черрика.Первый добавит файл с содержимым one.Второй попытается изменить это содержимое с four на five.

Увы, это содержимое не four.Таким образом, у вас есть конфликт.

Если ваша цель - получить от one до five без промежуточных коммитов, то вы хотите squash их или пометить как fixup коммитов.

pick 1111111 add one
pick 2222222 change one to two
squash 3333333 change two to three
squash 4444444 change three to four
squash 5555555 change four to five

В этом случае первое изменение будет выбрано черри, поэтому будет создан файл one.Последующее изменение будет выбрано черри, поэтому содержимое будет изменено с one на two.И последующие изменения будут отобраны, что приведет к дальнейшему обновлению файла, но эти изменения будут "сведены" в предыдущую фиксацию.Таким образом, вы получите полное содержимое, но в итоге получите только два коммита.

(Если бы вы пометили их как fixup коммитов, вы бы получили то же содержимое, но их сообщения коммита небыть включенным в предложенное вами сообщение о коммите.

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

В подобных ситуациях мне приходится вручную создавать свои коммиты

Конечная цель - создать журнал git, который выглядит следующим образом:
6937ddd CV 2019.01
4c802c1 Первоначальный коммит

  1. получить полный SHA1 первого коммита.Это понадобится вам позже.
    git rev-parse 70f72ca
  2. Извлечение объекта фиксации последнего коммита в текстовый файл.
    git cat-file commit 6937ddd > commit.txt
  3. Редактирование commit.txt.Измените строку parent с 7b51754.... на вывод из 1)
  4. Записать (пользовательский) объект коммита в вашу базу данных git cat commit.txt | git hash-object -t commit --stdin -w
  5. Tag / branch / reset -Хард SHA1, что вышеприведенная команда печатает.Вы должны увидеть желаемую историю.

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

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

Проблема в том, что git rebase использует противоречивую терминологию для определения того, как git в целом определяет коммиты.Коммит - это моментальный снимок, но rebase обрабатывает коммит как патч (набор изменений) между его родительским коммитом и самим собой.

Так что если вы скажете rebase «удалить коммит», ондумает, что вы хотите отменить изменения, примененные патчем этого коммита.

Если вы хотите удалить некоторые моментальные снимки, сохранив те же самые последующие снимки, вы сообщаете rebase - squash фиксации.В терминах rebase это означает, что вы объединяете изменения из нескольких коммитов в последний из этих коммитов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...