Подтвердить что ты не робот

Сквош два Git фиксируются в середине истории без интерактивной перестановки

Я собираюсь преобразовать старый SVN-репозиторий в Git, который включает попытку получить все ветки/теги во всех правильных местах. Эта часть идет неплохо, но есть моменты, когда я хочу добавить фиксацию в истории в свой script, который позже мне нужно сквош со следующей фиксацией. Проблема в том, что я не хватаю коммиты один за другим, но как большую группу, поэтому я не могу раздавить их, когда вытаскиваю их из репозитория SVN. В конце концов, мой репозиторий выглядит следующим образом:

* (branch_2, HEAD) commit 5
* commit 4
* commit 3
* SQUASH ME!
* (branch_1) commit 2
* commit 1

Я хочу иметь возможность скворовать commit 3 с помощью SQUASH ME!, что, очевидно, легко с интерактивной перестановкой, но более сложной из script. Основная проблема, которая, как мне кажется, заключается в том, что, хотя она легко проверяется branch_1 или какой-либо фиксацией до нее, сложно запрограммировать запрос после нее, и мне сложно предсказать, сколько из них возвращается из branch_2 Мне нужно идти. Я действительно хочу иметь возможность сделать что-то вроде:

git checkout branch_1+2

Любые указатели?

4b9b3361

Ответ 1

То, о чем вы говорите, это не сквош, а fixup, потому что сквош запросит у вас сообщение commit в интерактивном режиме, тогда как используется fixup сообщение фиксации из сообщения HEAD.

Здесь script, который делает это без вмешательства.

script: /usr/bin/git-fixup

#/bin/bash
# This command fixesup one commit onto his parent
set -e

# We need a commit from the first argument of that command
commit=${1:?No commit given as first argument}
startingbranch=$(git rev-parse --abbrev-ref HEAD)

# Checkout the parent of the asked commit
git checkout "$commit"
git checkout HEAD~

# Merge the commit into it parent, keeping the commit message of the parent
git merge --squash "$commit"
git add .
git add --update
git commit --amend --no-edit

# Store the current commit
newcommit=$(git rev-parse HEAD)

# Rebase the starting branch onto the new commit
git checkout "$startingbranch"
git rebase "$newcommit"

Используйте его с

git fixup <commit-id>

Например, если ваша история:

ce0e2fd (master, HEAD) commit 4
72ab3c4 commit 3
8150939 commit 2
301c1e1 commit 1

Вы можете сделать git fixup 72ab3c4, который объединит "commit 3" и "commit 2" в качестве фиксации с сообщением "commit 2" и поместит вас обратно на главную ветку.

Ответ 2

От git rebase --help:

- autosquash

Когда сообщение журнала фиксации начинается с "squash!..." (или "fixup!..." ), и есть фиксация, чье название начинается с того же..., автоматически изменяет список задач rebase -i так что фиксация, помеченная для раздавливания, появляется сразу после фиксации, которая будет изменена, и изменит действие перемещенного фиксации от выбора до сквоша (или исправления).

Эта опция действительна только при использовании опции -interactive.

Похоже, что он сделает половину того, что вы хотите, если вход находится в правильной форме.

Другая половина препятствует запуску интерактивного редактора. К счастью, редактор настраивается, поэтому мы можем просто установить его на что-то безопасное.

Попробуйте следующее:

env EDITOR=true git rebase -i --autosquash <from-here>

Настройка редактора на true (инструмент, который просто успешно завершается) достаточно, чтобы убедить git выполнить настройки переустановки по умолчанию, которые автокартф должен был установить на что-то полезное.


В качестве альтернативы, если --autosquash не делает то, что вам нужно, вы можете установить EDITOR на любой script, который вам нравится:

env EDITOR=mysquasher.sh git rebase -i <from-here>

script может делать все, что вам нужно, но в вашем случае ему нужно найти только каждую строку, содержащую "SQUASHME!", и изменить "pick" на следующую строку, чтобы прочитать "fixup". Скорее всего, это может быть достигнуто с помощью awk:

#!/bin/bash -e

awk -- 'BEGIN {dosquash=0}
        dosquash==1 {gsub(/^pick/, "fixup"); dosquash=0}
        /SQUASHME/ {dosquash=1}
        {print}' "$1" > /tmp/tmp.$$

mv /tmp/tmp.$$ "$1"