Как изменить порядок/объединить коммиты с помощью Git rebase?

После нескольких часов игры с rebase репо все еще выглядит не так, как мне нужно:

Я хотел бы выполнить следующие задачи:
[некоторые из которых были в порядке до того, как я начал возиться с перебазированием :( ]

  • Переместите Верхнюю фиксацию ("Удалены посторонние...") до отключения ветки (справа над "исправлением для # 226").
  • Объедините два коммита, которые находятся в ветке 'twist/main'. «Запятая» и «Перемещено загружено ...» должны быть одним и тем же коммитом, и мне вообще не нужно сообщение коммита «запятая».
  • Объедините недавно объединенный коммит «Moveloaded» с веткой «backup» и избавьтесь от «twist».
  • Переместите «мастер» туда, где теперь написано «резервное копирование».
  • Что означает этот тег «remote/origins/master»?

введите здесь описание изображения

Я понимаю, что это требует многого, но, пожалуйста, включите актуальные команды GIT.

Я не против прочитать и попробовать самостоятельно, но меня немного смущают результаты, не соответствующие моим ожиданиям, и я действительно не хочу случайно уничтожить какие-либо коммиты.


person SamGoody    schedule 17.01.2010    source источник
comment
Этот вопрос имеет довольно плохое название git rebase help и представляет собой серию отдельных операций, которые вы хотите выполнить. Попробуйте перефразировать это в форме одного вопроса. Первая цель, которую вы пытаетесь достичь, в форме вопроса, скорее всего, сделает остальные очевидными.   -  person Dustin    schedule 17.01.2010
comment
Я не думаю, что это плохой заголовок, это определенно проблема, требующая перебазирования коммитов.   -  person CB Bailey    schedule 17.01.2010
comment
Вы уверены, что хотите объединить ветки twist и backup? Я спрашиваю, потому что у них обоих есть коммиты с идентичными описаниями.   -  person CB Bailey    schedule 17.01.2010


Ответы (3)


Во-первых, переупорядочивание backup коммитов.

# Safety, should be a no-op if your gitk snapshot is accurate
git checkout backup

# Temporary branch
git branch backup-save backup

# Move top commit onto 'Fix for #226:
git rebase --onto origin/master HEAD^

# Go back to saved branch's parent (i.e. without the moved commit)
git reset --hard backup-save^

# Rebase onto the moved commit (HEAD@{1} is where HEAD was 1 step
# ago i.e. before the reset.)
git rebase HEAD@{1}

# Don't need the saved branch any more (although you might want
# to keep it for a bit just in case). This deletes it:
git branch -D backup-save

Объедините два коммита при повороте, игнорируя верхнее сообщение коммита.

git checkout twist

git reset --soft HEAD^

# Just re-save the commit message, alternatively to skip the
# editor step do this: git commit --amend -C HEAD
git commit --amend

Объедините ветку twist в backup, удалите ветку скручивания.

git checkout backup
git merge twist
git branch -d twist

Переместить master. Есть несколько причудливых способов, но это самый простой. Я предполагаю, что вы хотите, чтобы master указывало на отредактированную позицию backup, а не на исходную позицию.

git checkout master
git reset --hard backup

remote/origins/master — это ветка удаленного отслеживания, которая сообщает вам, где находится указатель ветки для ветки master в удаленном репозитории origin, или, точнее, был, когда вы в последний раз извлекали, нажимали или извлекали.

person CB Bailey    schedule 17.01.2010
comment
Вау, ты хорош. 1. На шагах «git checkout покрутить» не удалось объединить два коммита в ветке покрутки. Это должно было быть, или я что-то упустил? Он жалуется: КОНФЛИКТ (контент): конфликт слияния в Source/Depender.js Автоматическое слияние не удалось; исправить конфликты, а затем зафиксировать результат. ‹br› Как исправить конфликты? - person SamGoody; 17.01.2010
comment
Подождите, я знаю, как исправить конфликты с помощью git add. Через минуту отчитаюсь, либо еще больше запутался, либо всем доволен. - person SamGoody; 17.01.2010
comment
Хотя у меня не совсем получилось выполнить эти два шага, они достаточно приблизили меня к достижению цели. Все что вы написали понятно и по делу. Большое спасибо. - person SamGoody; 17.01.2010

Как не бояться

Я хотел бы показать вам, что как бы сильно вы ни накосячили, коммиты никогда не уничтожаются*, и вы всегда можете вернуться к тому, с чего начали.

Я сделал искусственное дерево git, которое имеет ту же форму, что и вы:

Теперь я собираюсь стереть последние три коммита из ветки «резервное копирование»:

$ git log --oneline
9b41f46 Removed extraneous whitespace
981e2e8 Merged the "loadscripts" function
005bc62 Pick up a few very fringe cases
07e71d9 Merged "getDepsForScript" function
...
$ git reset --hard HEAD~3
HEAD is now at 07e71d9 Merged "getDepsForScript" function
$ git log --oneline
07e71d9 Merged "getDepsForScript" function
...

Упс, это было плохо. Вернемся к тому, с чего мы начали. Сначала посмотрите, что мы сделали:

$git reflog
07e71d9 HEAD@{0}: HEAD~3: updating HEAD
9b41f46 HEAD@{1}: commit: Removed extraneous whitespace
...

Вы можете видеть, что когда мы перезагружались, все, что сделал git, — это заставило HEAD указывать на этот старый коммит. Но на самом деле никакие коммиты не были потеряны — они просто стали сиротами, а не частью какой-либо ветки. Давайте снова сделаем их частью ветки «backup»:

$ git reset --hard 9b41f46
HEAD is now at 9b41f46 Removed extraneous whitespace
$ git log --oneline
9b41f46 Removed extraneous whitespace
981e2e8 Merged the "loadscripts" function
005bc62 Pick up a few very fringe cases
07e71d9 Merged "getDepsForScript" function
...

Git означает, что вам никогда не придется извиняться.

* Незакрепленные объекты в конечном итоге удаляются сборщиком мусора, но не раньше, чем им исполнится не менее двух недель.

Как делать то, что вы хотите.

Сначала давайте объединим два коммита в master:

$ git checkout master
$ git rebase -i HEAD~2

Git запустит ваш редактор. Измените это:

pick 6389f4e Moved "loaded" function out of "require".
pick 41fb646 comma

к этому:

pick 6389f4e Moved "loaded" function out of "require".
s 41fb646 comma

И сохранить. Git снова запустит ваш редактор. Измените это:

# This is a combination of two commits.
# The first commit's message is:

Moved "loaded" function out of "require".

# This is the 2nd commit message:

comma

к этому:

Moved "loaded" function out of "require".

и сохранить.

Теперь давайте изменим порядок коммитов в «резервной копии»:

$ git checkout backup
$ git rebase -i remotes/origin/master

Когда появится ваш редактор, измените это:

pick ec7f71c moved "loaded" function out of "require"
pick 4a76897 Replaced maploaded event
pick 07e71d9 Merged "getDepsForScript" function
pick 005bc62 Pick up a few very fringe cases
pick 981e2e8 Merged the "loadscripts" function
pick 9b41f46 Removed extraneous whitespace             <-----

к этому:

pick 9b41f46 Removed extraneous whitespace             <-----
pick ec7f71c moved "loaded" function out of "require"
pick 4a76897 Replaced maploaded event
pick 07e71d9 Merged "getDepsForScript" function
pick 005bc62 Pick up a few very fringe cases
pick 981e2e8 Merged the "loadscripts" function

и сохранить.

Теперь вишневый выбор объединенной фиксации «Перемещено загружено» с мастера на текущую ветку («резервная копия»)

$git cherry-pick master

Укажите master на ту же фиксацию, что и «резервная копия».

$git checkout master
$git reset --hard backup

Избавьтесь от ветки поворота

$git branch -D twist
person Wayne Conrad    schedule 17.01.2010
comment
Сэм, с удовольствием. И это не просто выражение — я получаю массу удовольствия и многому учусь, когда выбираю вопрос на грани того, с чем я знаком. - person Wayne Conrad; 17.01.2010
comment
+1. Другая полезная команда для возврата старых коммитов: fsck (freeasinbeard.org/post/318519782/) - person VonC; 17.01.2010

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

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

  • Чтобы объединить две фиксации, вы можете выполнить интерактивную перебазировку.

  • Чтобы выбрать один коммит из одной ветки и применить его к другой, а в целевой ветке используйте git cherry-pick. Вы можете удалить старую ветку, используя git branch -D twist, когда закончите.

Надеюсь, эти советы помогут вам на пути к цели.

person jkp    schedule 17.01.2010