Как тривиально линеаризую мою историю git?
Вопрос
Учитывая, что у меня есть фиксация следующим образом:
A - B - C - D - G - H
\ /
- E - F -
Как получить совершенно линейную историю после первых родителей?
Например, я хочу получить:
A - B - C - D - G'- H'
Ожидается, что sha1 из G и H изменится, как указано выше. (По понятным причинам). Если sha1 для A, B, C и D также изменится, тогда я хочу знать, почему.
Фон
Цель состоит в том, чтобы избежать возможных коммандов слияния, которые возникли бы при выполнении наивной git rebase -i.
Реальная задача - надеяться получить дополнительную информацию, чтобы определить, какие коммиты находятся в конкретной ветки, например, если у нас есть следующий график:
I - J - K - L - M
\ / / /
- N - O - P -
Где N было объединено в K, но O было объединено с -strategy = ours в L, а P было объединено в M.
Я хочу, чтобы иметь возможность линеаризовать мою историю, чтобы такие проблемные фиксации можно было идентифицировать и проверить. Я хочу иметь дерево, где можно определить, что O не было помещено в ветвь вверх по течению, даже если я потенциально идентифицирую N и P как потенциально отсутствующие в ветке вверх по течению, используя git cherry, однако любые предложения здесь быть оцененным.
Ответы
Ответ 1
Как вы сказали, работает следующая команда:
git filter-branch --parent-filter 'cut -f 2,3 -d " "'
Почему?
Задача, которую вы ставите, решается путем преобразования каждого объединения с простым фиксацией: это просто удалит ветки функций, которые были объединены, поскольку они станут сиротами.
Каждая фиксация имеет одну или несколько операндов. Merge commit - это тот, который получает больше одного. Git сохраняет это в каждом объекте фиксации истории.
Команда git filter-branch
с параметром --parent-filter
позволяет переписать каждый родитель фиксации, переданный фильтру как -p SHA1
, повторяющийся, если имеется более одного родителя. Наш фильтр отсекает родителя и заставляет каждую фиксацию иметь одного родителя.
Для бонуса, здесь, как сделать это вручную при точном фиксации, путем повторного создания нового фиксации:
-
получить дерево фиксации и первый родительский
tree=`git show -s --format=%T SHA1`
parent=`git show -s --format=%P SHA1 | cut -d " " -f1`
-
сделать новую фиксацию с тем же деревом, тем же сообщением и сохранить только первого родителя в качестве предка
git show -s --format=%B SHA1 | git commit-tree $tree -p $parent
Ответ 2
Сделайте это вручную со следующим:
git rebase -i D-sha1
Отредактируйте файл, чтобы установить G в "edit". Храните "pick" для H. Сохраните и закройте редактор.
Теперь Git позволяет редактировать G commit, а затем модифицировать его в сквош-слияние F-фиксации. Вы хотите:
#cancel the merge commit and position HEAD to D
git reset --hard HEAD~
#squash merge and continue
git merge --squash F-sha1
git rebase --continue
Обратите внимание, что вам придется решать те же конфликты, если вам пришлось в первом слиянии...
Как вы говорите, у вас будет только новый SHA1 для G и H.