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

Переопределение коммитов

В настоящее время я работаю над веткой и хочу, чтобы некоторые коммиты сливались в другие ветки:

    a-b-c-d-e-f-g (branchA)
   /
--o-x-x-x-x-x-x-x-x-x-x (master)
   \
    x-x-x-x-x (branchB)

(Буквы обозначают фиксации, а "x" не имеют значения.)

Однако я заметил, что было бы неплохо объединить некоторые коммиты. Я хочу "конкатенировать" фиксацию a, d, e и g в один патч и передать его в мастер. Записывает b и f, чтобы они выполнялись как один фиксатор для ветки. Есть ли хороший способ "git" - ish для его достижения?

4b9b3361

Ответ 1

Команда, которую вы ищете, это git rebase, в частности параметр -i/--interactive.

Я собираюсь предположить, что вы хотите оставить commit c на ветке A, и что вы действительно имеете в виду, что хотите переместить другие коммиты в другие ветки, а не слияния, поскольку слияния просты. Пусть начнется манипуляция веткой А.

git rebase -i <SHA1 of commit a>^ branchA

^ означает предыдущую фиксацию, поэтому эта команда говорит, чтобы перераспределить ветвь A, используя фиксацию до "a" в качестве базы. Git представит вам список коммитов в этом диапазоне. Измените порядок и скажите Git, чтобы сквоить соответствующие:

pick c ...
pick a ...
squash d ...
squash e ...
squash g ...
pick b
squash f

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

    c - [a+d+e+g] - [b+f] (branchA)
   /
--o-x-x-x-x-x-x-x-x-x-x (master)

Теперь позвольте захватить недавно сжатый фиксатор b + f для ветки B.

git checkout branchB
git cherry-pick branchA  # cherry-pick one commit, the tip of branchA

И то же самое для a + d + e + g для мастера:

git checkout master
git cherry-pick branchA^

Наконец, обновите ветвь A, чтобы она указывала на c:

git branch -f branchA branchA^^

Теперь мы должны иметь:

    c (branch A) - [a+d+e+g] - [b+f] (dangling commits)
   /
--o-x-x-x-x-x-x-x-x-x-x-[a+d+e+g] (master)
   \
    x-x-x-x-x-[b+f] (branchB)

Обратите внимание, что если у вас было несколько коммитов, которые вы хотели переместить между ветвями, вы можете снова использовать rebase (не интерактивно):

# create a temporary branch
git branch fromAtoB branchA
# move branchA back two commits
git branch -f branchA branchA~2
# rebase those two commits onto branchB
git rebase --onto branchB branchA fromAtoB
# merge (fast-forward) these into branchB
git checkout branchB
git merge fromAtoB
# clean up
git branch -d fromAtoB

Наконец, отказ от ответственности: вполне возможно переупорядочить фиксации таким образом, что некоторые из них более не применяются. Это может быть связано с тем, что вы выбрали плохой порядок (установив патч перед фиксацией, введя исправленную функцию); в этом случае вам нужно отменить rebase (git rebase --abort). В противном случае вам придется разумно исправлять конфликты (как и при конфликтах слиянием), добавлять исправления, а затем запускать git rebase --continue для перехода. Эти инструкции также предоставляются сообщением об ошибке, которое отображается при возникновении конфликта.

Ответ 2

git rebase --interactive - это команда, которую вы хотите.

Пример:

Текущий статус:

[email protected]:~/src/stackoverflow/reordering_of_commits
$ git status
On branch master
nothing to commit, working tree clean
[email protected]:~/src/stackoverflow/reordering_of_commits
$ git log --oneline
a6e3c6a (HEAD -> master) Fourth commit
9a24b81 Third commit
7bdfb68 Second commit
186d1e0 First commit

Я хочу изменить порядок коммитов 9a24b81 (Третий коммит) и 7bdfb68 (Второй коммит). Для этого я сначала нахожу коммит перед первым коммитом, который мы хотим изменить. Это коммит 186d1e0 (Первый коммит).

Команда для выполнения - git rebase --interactive COMMIT-BEFORE-FIRST-COMMIT-WE-WANT-TO-CHANGE, в данном случае:

[email protected]:~/src/stackoverflow/reordering_of_commits
$ git rebase --interactive 186d1e0

Это открывает файл в редакторе по умолчанию со следующим содержанием:

pick 7bdfb68 Second commit
pick 9a24b81 Third commit
pick a6e3c6a Fourth commit

# Rebase 186d1e0..a6e3c6a onto 186d1e0 (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#

Обратите внимание, что порядок коммитов в файле противоположен порядку, используемому для git log. В git log самый последний коммит находится сверху. В этом файле самый последний коммит находится внизу.

Как поясняет комментарий внизу файла, я могу делать разные вещи, такие как сжатие, отбрасывание и изменение порядка коммитов. Чтобы изменить порядок фиксации, я редактирую файл так, чтобы он выглядел следующим образом (нижние комментарии не отображаются):

pick 9a24b81 Third commit
pick 7bdfb68 Second commit
pick a6e3c6a Fourth commit

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

$ git rebase --interactive 186d1e0
Successfully rebased and updated refs/heads/master.
[email protected]:~/src/stackoverflow/reordering_of_commits
$ git log --oneline
ba48fc9 (HEAD -> master) Fourth commit
119639c Second commit
9716581 Third commit
186d1e0 First commit

Обратите внимание на переписанную историю коммитов.

Ссылки:

Ответ 3

Если вы хотите переупорядочить только последние две коммиты, вы можете использовать этот псевдоним git reorder: fooobar.com/questions/131761/...

Ответ 4

git rebase - это то, что вы хотите. Проверьте параметр -interactive.

Ответ 5

git rebase -i HEAD~3

Где 3 - количество коммитов, которые необходимо переупорядочить (источник).

Откроется vi, в котором будут зафиксированы коммиты от самой старой (вверху) до самой новой (внизу).
Теперь измените порядок строк, сохраните и выйдите из редактора.

ddkP переместит текущую строку вверх (источник)
ddp переместит текущую строку вниз