Git: Як перейти на певний комітет?


154

Мені хотілося б перейти до конкретного комітету, а не до керівника іншої галузі:

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

до

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

замість

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

Як я можу цього досягти?


4
Ви пробували робити git checkout Bперед бігом git rebase?
Пітер-Пол ван Гемерден

Ні, чи варто це допомагати? Напевно, rebaseважливі лише посилання команди.
Ondra Žižka

Відповіді:


98

Ви можете уникнути використання параметра --onto, зробивши тимчасову гілку на вподобаному вами зобов'язанні, а потім скористайтеся ребазом у його простому вигляді:

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

5
Мені більше подобається такий підхід RISC :) Спробую. Дякую.
Ondra Žižka

10
Цікаво, чому це не працює для мене, за дещо іншим сценарієм . Я хочу , щоб група пропустити pep8 і грунтуватися на майстра . git rebase temp(коли в групі ) відмовляється від "Актуальні групи філій актуальні".
Алоїс Магдал

4
Це рішення не працюватиме за сценарієм, коли тема вже була переобладнана на головний, але ви хочете перезавантажити її на предка для освоєння. У цьому випадку ви повинні використовувати git rebase --onto <target> <from> <to>так, щоб ви могли вказати <from> фіксацію.
mirzmaster

Це, безумовно, найпростіший варіант, якщо ви хочете повторно встановити ту саму комісію, на якій базується гілка.
Еш

1
Я, здається, працює, але GitLab говорить щось інше. Якщо у мене було 10 комітів позаду, 5 перемог вперед, моє сподівання було 8 запізнень, 5 перемог вперед після отримання 2 комітів. Але замість цього він додає більше зобов’язань для тих 5
ROMANIA_engineer

67

Можна навіть скористатися прямим підходом:

git checkout topic
git rebase <commitB>

6
Для мене це насправді не робить те, що призначено. Наскільки я можу сказати, він намагається переосмислити "останнього спільного предка" topicта commitB.
Дан Ленськи

2
@DanLenski, це не так, як працює база даних. Цитуючи документи , It works by going to the common ancestor of the two branches (the one you’re on and the one you’re rebasing onto), getting the diff introduced by each commit of the branch you’re on, saving those diffs to temporary files, resetting the current branch to the same commit as the branch you are rebasing onto, and finally applying each change in turn. я спробував це ще раз і, здавалося, працює добре.
r0hitsharma

1
Супер легко і працює! Зараз у мене: commitB_from_master-> topicCommit1-> topicCommit2.
Мартін Конічек

Це не працювало для мене. Перед цим GitLab заявив, що "n поступається вперед". А тепер там сказано, "куди я вперед" куди m > n.
ROMANIA_engineer

48

Скористайтеся опцією "на":

git rebase --onto master^ D^ D

2
Dі D^чи буде хеш останнього та наступного останнього комітету "теми"?
Ondra Žižka

39
Синтаксис схожий git rebase --onto <new-parent> <old-parent>. Див. Розділ Налаштування вказівника батьків git на інший батьків . У вашому випадку <new-parent> - B, а <old-parent> - A.
jsz

7
Я завжди використовую 3 аргументи: дезинація, початок і кінець комісій для перезавантаження.
Адам Дімітрук

14
Це працювало для мене:git rebase --onto <commit-ID> master

4
@ jsz коментар правильний, всупереч коментарю Саймона Саута, навпаки: git rebase --onto master <commit-ID-of-old-parent>і для ОП git rebase --onto B A.
габоровий

19

Коментар jsz вище врятував мені тонни болю, тож ось покрокова репліка на її основі, яку я використовував для перезавантаження / переміщення будь-якого комітету поверх будь-якої іншої комісії:

  1. Знайдіть попередню точку розгалуження гілки, яку потрібно перебазувати (перемістити) - назвіть її старим батьківським. У наведеному вище прикладі це A
  2. Знайдіть комісію, зверху до якої ви хочете перемістити гілку - називайте її новим батьківським. В іспиті, що B
  3. Вам потрібно бути у своїй філії (тій, яку ви переміщуєте):
  4. Застосуйте свою базу даних: git rebase --onto <new parent> <old parent>

У наведеному вище прикладі це так просто, як:

   git checkout topic
   git rebase --onto B A

6
Це має бути правильна відповідь. Окрім того, що я використовую git rebase --onto B master, див. Мою відповідь для більш ретельного пояснення.
Зак Морріс

Для мене це не спрацювало нормально. Я вибрав 2 послідовних коміти (останній з головного, який був у поточній гілці, і перший з головного, який не був у поточній гілці). Я почав зі 100 позаду - 10 вперед, а замість 99 позаду - 10 попереду, тепер маю 105 позаду - 13 попереду.
ROMANIA_engineer

Вибачте, що це не спрацювало. Звучить, що ваші гілки розходяться зовсім небагато - я б запропонував спочатку обрізати їх, перш ніж спробувати відновити гілки з такою кількістю відмінностей.
Нестор

11

Тематичне рішення

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

git rebase --onto B master
git rebase --onto master~1 master
git rebase --onto B A
git rebase --onto B C
git rebase --onto B

Якщо topicце не встановлено, ви просто додаєте topicдо команди (крім останньої) так:

git rebase --onto B master topic

Як варіант, спочатку ознайомтеся з відділенням:

git checkout topic

Обновіть будь-які рядки комісій для цільового комітету

Основна форма команди, яка нам потрібна, прошита з документації, - це:

git rebase --onto <Target> [<Upstream> [<Branch>]]

<Branch>необов’язково, і все, що він робить, - це перевірити вказану гілку перед виконанням решти команди. Якщо ви вже перевірили галузь, яку хочете відновити, тоді вам це не потрібно. Зауважте, що ви повинні вказати <Upstream>, щоб вказати, <Branch>чи git вважатиме, що ви вказуєте <Upstream>.

<Target>це зобов'язання, до якого ми будемо приєднувати наш ряд рядків. Надаючи назву філії, ви просто вказуєте команду голови цієї гілки. <Target>може бути будь-яка комісія, яка не міститиметься в рядку переміщених комісій. Наприклад:

A --- B --- C --- D         master
      \
       \-- X --- Y --- Z    feature

Щоб перемістити всю гілку функції, ви не можете вибрати X, Y, Zабо featureяк <Target>так як ті всі коммітов всередині групи переміщення.

<Upstream>є особливим, оскільки може означати дві різні речі. Якщо це коміт, який є родоначальником перевіреної гілки, то він служить точкою зрізу. У цьому прикладі я представив, це було б нічого , що ні C, Dабо master. Усі зобов’язання після закінчення, <Upstream>поки керівник перевіреного відділення не буде переміщений.

Однак, якщо <Upstream>це не пращур, то git створює резервну копію ланцюга від зазначеної фіксації до тих пір, якщо не знайде спільного предка з перевіреною гілкою (і скасовує, якщо її не може знайти). У нашому випадку, <Upstream>з B, C, Dабо masterбуде весь результат фіксації , Bвиступаючим в якості точки розрізу. <Upstream>сама по собі є необов'язковою командою, і якщо вона не вказана, то git дивиться на батьківську адресу перевіреної гілки, що є еквівалентом введення master.

Тепер, коли git вибрав комітети, які він скоротить і перемістить, він застосовує їх для того, щоб <Target>пропустити всі, які вже застосовані до цілі.

Цікаві приклади та результати

Використовуючи цю вихідну точку:

A --- B --- C --- D --- E         master
            \
             \-- X --- Y --- Z    feature
  • git rebase --onto D A feature
    Буде чи застосовуватися фіксацій B, C, X, Y, Zзробити Dі в кінцевому підсумку пропуск Bі Cтому , що вони вже були застосовані.

  • git rebase --onto C X feature
    Застосовуватиме зобов’язання Yта Zвиконувати зобов'язання C, ефективно видаляючи комісіюX


4

Більш просте рішення git rebase <SHA1 of B> topic. Це працює незалежно від місця вашого HEADперебування.

Ми можемо підтвердити цю поведінку з git rebase doc

<upstream>Вища гілка для порівняння проти. Може бути будь-яка дійсна комісія , а не лише існуюча назва філії. За замовчуванням налаштований вище за поточною гілкою.


Ви можете думати, що станеться, якщо я згадаю SHA1 topicзанадто у вищевказаній команді?

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

Це також буде працювати, але перезавантаження потім не Topicвказуватиме на нову гілку, створену таким чином, і HEADперебуває у відокремленому стані. Тож звідси ви повинні вручну видалити стару Topicта створити нову посилання гілки на новій гілці, створеній за допомогою rebase.


3

Я використовував суміш розчинів, описаних вище:

$ 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".

1
тут же, у кількох файлах виникли конфлікти, коли я використовував 2 найпопулярніших відповіді (тобто, r0hitsharma та Dymitruk)
Олівер

3

Оскільки звільнення є настільки принциповим, ось розширення відповіді Нестора Міляєва . Поєднання jsz - х і Саймона Півдня коментарі відповідь Адам Dymitruk в дає команду , яка працює на 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

Отже, остання команда - це та, яку я зазвичай використовую.


-2

Існує й інший спосіб зробити це, або якщо ви хочете перейти до більш ніж одного виконання.

Ось приклад повернення до nкількості комітетів:

git branch topic master~n

Заради цього питання це також можна зробити:

git branch topic master~1

Команда прекрасно працює на git version 2.7.4. Не перевіряли його в будь-якій іншій версії.


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