Git: как переустановить конкретную фиксацию?

Я хотел бы переустановить конкретную фиксацию, а не HEAD другой ветки:

A --- B --- C          master
 \
  \-- D                topic

к

A --- B --- C          master
       \
        \-- D          topic

вместо

A --- B --- C          master
             \
              \-- D    topic

Как я могу это достичь?

Ответ 1

Вы можете избежать использования параметра --onto, создав ветвь temp на комманде, который вам нравится, а затем используйте в нем базовую форму:

git branch temp master^
git checkout topic
git rebase temp
git branch -d temp

Ответ 2

Вы даже можете сделать прямой подход:

git checkout topic
git rebase <commitB>

Ответ 3

Используйте опцию "на":

git rebase --onto master^ D^ D

Ответ 4

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

  1. Найдите предыдущую точку ветвления ветки, которую нужно перебазировать (переместить) - назовите ее старым родителем. В приведенном выше примере, что А
  2. Найдите коммит, поверх которого вы хотите переместить ветку - назовите его новым родителем. В экзамене, что B
  3. Вы должны быть на своей ветке (той, которую вы перемещаете):
  4. Примените свою rebase: git rebase --onto <new parent> <old parent>

В приведенном выше примере это так просто, как:

   git checkout topic
   git rebase --onto B A

Ответ 5

Я использовал смесь решений, описанных выше:

$ git branch temp <specific sha1>
$ git rebase --onto temp master topic
$ git branch -d temp

Мне стало намного легче читать и понимать. Принятое решение привело меня к конфликту слияния (слишком ленив, чтобы исправить вручную):

$ git rebase temp
First, rewinding head to replay your work on top of it...
Applying: <git comment>
Using index info to reconstruct a base tree...
M       pom.xml
.git/rebase-apply/patch:10: trailing whitespace.
    <some code>
.git/rebase-apply/patch:17: trailing whitespace.
        <some other code>
warning: 2 lines add whitespace errors.
Falling back to patching base and 3-way merge...
Auto-merging pom.xml
CONFLICT (content): Merge conflict in pom.xml
error: Failed to merge in the changes.
Patch failed at 0001 <git comment>
The copy of the patch that failed is found in: .git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

Ответ 6

Есть другой способ сделать это, или если вы хотите вернуться к более чем одному коммиту.

Вот пример для возврата к n количеству коммитов:

git branch topic master~n

Ради этого вопроса это также может быть сделано:

git branch topic master~1

Команда отлично работает на git version 2.7.4. Не проверял ни на одной другой версии.

Ответ 7

Поскольку перебазирование является настолько фундаментальным, вот ответ Нестора Миляева. Объединение комментариев jsz и Саймона Юга из ответа Адама Димитрука дает эту команду, которая работает в ветке topic независимо от того, веткится ли она из коммита master ветки A или C:

git checkout topic
git rebase --onto <commit-B> <pre-rebase-A-or-post-rebase-C-or-base-branch-name>

Обратите внимание, что последний аргумент обязателен (в противном случае он перематывает вашу ветку для фиксации B).

Примеры:

# if topic branches from master commit A:
git checkout topic
git rebase --onto <commit-B> <commit-A>
# if topic branches from master commit C:
git checkout topic
git rebase --onto <commit-B> <commit-C>
# regardless of whether topic branches from master commit A or C:
git checkout topic
git rebase --onto <commit-B> master

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

Ответ 8

Более простое решение - git rebase <SHA1 of B> topic. Это работает независимо от того, где находится ваша HEAD.

Мы можем подтвердить это поведение из git rebase doc

<upstream> ветка <upstream> для сравнения. Может быть любой допустимый коммит, а не просто существующее имя ветки. По умолчанию настроен восходящий поток для текущей ветки.


Вы можете подумать, что произойдет, если я упомяну SHA1 topic тоже в приведенной выше команде?

git rebase <SHA1 of B> <SHA1 of topic>

Это также будет работать, но перебазирование не будет приводить к тому, что Topic указывать на новую ветвь, созданную таким образом, и HEAD будет в отдельном состоянии. Отсюда вы должны вручную удалить старую Topic и создать новую ссылку на новую ветку, созданную rebase.