Переупорядкування комітетів


104

Зараз я працюю над філією і хочу, щоб деякі зобов'язання були об'єднані в інші гілки:

    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)

(Букви позначають коміти, а "х" - нерелевантні коміти.)

Однак я помітив, що було б гарною ідеєю об'єднати деякі комісії. Я хочу "об'єднати" поступки a, d, e і g в один патч і зобов'язати його освоїти. Коміти b і f повинні виконуватись як один прихильний зв'язокB. Чи є хороший "git'-ish" спосіб його досягнення?


4
У двох відповідях, які вже були наведені, згадується правильна команда, але я думаю, що з такою базовою задачею, як ця, варто мати справжні інструкції тут на StackOverflow, тому я опублікував декілька. (Я здивований, я не можу знайти хорошого попереднього запитання, на який можна посилатись.)
Каскабель

Відповіді:


125

Команда, яку ви шукаєте, - це git rebaseконкретно -i/--interactiveваріант.

Я припускаю, що ви хочете залишити команду c на гілці A, і що ви дійсно означаєте, що хочете перемістити інші коміти в інші гілки, а не зливатися, оскільки злиття є прямими. Почнемо з маніпулювання гілкою А.

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

В ^означає попередній Комміт, тому ця команда говорить перебазуватися гілка А з допомогою фіксації , перш ніж «а» в якості основи. 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

І те саме для + d + e + g для master:

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)

Зауважте, що якщо у вас було декілька комітетів, які ви хотіли переміщати між гілками, ви можете знову використовувати ребайт (неінтерактивно):

# 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

Нарешті, відмова від відповідальності: Цілком можливо змінити порядок здійснення зобов’язань таким чином, що деякі більше не застосовують чисто. Це може бути тому, що ви вибрали поганий порядок (накладення виправлення перед фіксацією, введення функції, яку він виправляв); у такому випадку вам потрібно скасувати ребазу ( git rebase --abort). Інакше вам доведеться розумно виправляти конфлікти (так само, як це стосується конфліктів злиття), додавати виправлення, а потім бігти, git rebase --continueщоб рухатися далі. Ці інструкції також надаються повідомленням про помилку, надрукованим під час конфлікту.


чи не діаграма після git branch -f branchA branchA^^неправильної? А саме, чи не слід відгалуженняA вказувати на c в цій точці, так що перший рядок діаграми є, c (branchA)а ні c - [a+d+e+g] - [b+f] (branchA)?
ntc2

@enoksrd: Так, є помилка, але у вашій редакції були помилки. Я це виправлю, коли отримаю можливість тут.
Каскабель

Замість того, щоб робити, git branch -f branchA branchA^^чому ви не можете просто зробити git reset --hard <sha1 of c>на гілці A?
Михайло Васильєв

17
git rebase -i HEAD~3

Де 3кількість комісій, які потребують переупорядкування ( джерело ).

Це відкриє vi , перерахування комісій від найдавнішого (верхній) до найновішого (нижнього).
Тепер упорядкуйте рядки, збережіть та вийдіть із редактора.

ddpперемістить поточну лінію вниз
ddkP , перемістить поточну лінію вгору ( джерело )


9

git rebase --interactive це команда, яку ви хочете.

Приклад:

Поточний статус такий:

bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git status
On branch master
nothing to commit, working tree clean
bernt@le3180:~/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цьому випадку командою для виконання є :

bernt@le3180:~/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's 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. У журналі git найновіша фіксація знаходиться вгорі. У цьому файлі найновіша комітка знаходиться внизу.

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

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

pickКоманда на початку кожного засіб лінії «використання (тобто включати в себе) це зробити» і при збереженні тимчасового файлу з командами перебазуватися і вийти з редактора, Git буде виконувати команди і оновлення сховища і робочий каталог:

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

Зверніть увагу на переписану історію комісій.

Посилання:


1
Будь ласка, додайте відповідні деталі зі свого посилання, щоб забезпечити повну і незалежну відповідь. Так нахмуриться на "відповіді лише для посилань". Зокрема, як можна використовувати git rebase --interactiveдля досягнення мети ОП?
SherylHohman

Друга посилання зараз не існує.
розроблений

Додано вміст, щоб зробити відповідь повноцінною та самостійною. Видалено друге посилання.
кодеп


-1

git rebase - те, що ви хочете. Ознайомтеся з - інтерактивним варіантом.


4
Будь ласка, додайте відповідні деталі зі свого посилання, щоб забезпечити повну і незалежну відповідь. Так нахмуриться на "відповіді лише для посилань".
SherylHohman
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.