Найти точку перебазирования - PullRequest
0 голосов
/ 11 сентября 2018

Скажите, у меня есть это:

I1 -- I2 -- I3 
 \            \
  F1 -- F2 -- ? -- F3 -- F4 -- F5

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

Итак, я делаю:

git fetch origin I
git checkout F
git rebase origin/I

Так что теперь это должно выглядеть примерно так:

I1 -- I2 -- I3
               \
               F1 -- F2 -- F3 -- F4 -- F5

мой вопрос - теперь я хочу раздавить коммиты F1-F5 в один коммит. Как я могу безопасно раздавить коммиты?

Я могу сделать git reset --soft x, но что такое x? Как я могу найти, на какой коммит вернуться? Я не хочу терять историю из ветки интеграции.

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

Ответы [ 2 ]

0 голосов
/ 11 сентября 2018

TL; DR

Попробуйте git fetch && GIT_SEQUENCE_EDITOR="sed -i '' 's/^pick/squash/'" git rebase -i @{u} (вы можете сжать это в псевдоним, оболочку или Git-to-shell).

Long

Рассмотрите следующее: Когда вы запускаете git rebase, , вы указываете git rebase, куда помещать копии .То есть вы запускаете:

git checkout $branch
git rebase $onto

, где $branch - это имя вашей ветви, а $onto - это то, что определяет, как выполнить ребазинг.Поскольку копии идут после , фиксация, указанная $onto, $onto автоматически становится правильной точкой для вашего git reset --soft.

Если у вас есть git pull --rebase, запустите git rebase дляВы отказываетесь от прямого контроля $onto здесь.Команда git pull сначала запускает git fetch $remote для некоторых $remote, а затем использует извлеченную информацию, которую git fetch записывает (в $GIT_DIR/FETCH_HEAD), в качестве параметра $onto.

Есть немногоздесь сложность из-за кода разветвления, но в современном Git у вас есть преимущество в том, что git fetch обновит $upstream, где $upstream - восходящий поток текущей ветви, после чего git rebase будет использовать $upstream и автоматически выполняйте все операции разветвления, чтобы $upstream оставался верным.В этом случае использование:

. git-sh-setup
branch=$(git symbolic-ref -q --short HEAD) || die 'not currently on a branch'
remote=$(git config --get branch.$branch.remote) || die 'current branch has no upstream'
git fetch $remote && git rebase || die 'fetch or rebase failed'
git reset --soft $upstream && git commit

в качестве сценария (названного, например, git-rebase-and-squash в вашем $PATH и запускаемого как git rebase-and-squash) в большинстве случаев поможет.

Вместо того, чтобы использовать reset --soft и git commit напрямую, вы можете прочитать последнюю строку:

GIT_SEQUENCE_EDITOR="sed -i '' 's/^pick/squash/'" git rebase -i $upstream

, которая преобразует все pick s в squash es для вас,и в этом случае вам даже не понадобится более ранний git rebase, так что весь сценарий сворачивается до git fetch, за которым следует git rebase -i @{upstream}.(Если вы все еще хотите автоматизировать редактирование последовательности, решать только вам.)

Если вы не возражаете против слегка вводящих в заблуждение сообщений об ошибках, вам также не нужна проверка.Выполнение git fetch будет по умолчанию извлекать из origin, а @upstream будет сбои с шумом, если нет текущей ветви или , если у текущей ветви нет восходящего потока, так что это может быть уменьшено до двухСценарий или псевдоним длинной команды:

git fetch && GIT_SEQUENCE_EDITOR="sed -i '' 's/^pick/squash/'" git rebase -i @{u}
0 голосов
/ 11 сентября 2018

Если вы хотите сдавить с помощью мягкого сброса, выполните:

git reset --soft HEAD~5

Это переместит указатель HEAD из текущей позиции в F5 обратно в I3 коммит.Но программный сброс не будет касаться как рабочего каталога, так и рабочей области.Таким образом, чистым эффектом будет то, что ваша сцена будет отражать коммиты 5 F.Затем, когда вы совершите коммит, вы фактически раздавите эти 5 коммитов до одного:

git commit -m 'squashed 5 F commits'

Это оставит вас с:

I1 -- I2 -- I3 -- C

В качестве альтернативы вы также можете сделать интерактивныйrebase:

git rebase -i HEAD~5

Вы должны изменить каждый коммит, который вы хотите раздавить, с pick на squash, а затем завершить ребаз.

...