Hg: Як зробити ребауз, як ребат git


207

У Git я можу це зробити:

1. Почніть працювати над новою функцією:
$ git co -b newfeature-123 # (галузь розвитку місцевих функцій)
зробіть кілька комітів (M, N, O)

майстер A --- B --- C
                \
новахарактеристика-123 M --- N --- O

2. Витягніть нові зміни з головного потоку:
$ git тягнути
(master оновлено ff-commits)

майстер A --- B --- C --- D --- E --- F
                \
новахарактеристика-123 M --- N --- O

3. Перезавантажте майстер, щоб отримати мою нову функцію 
може бути розроблено на основі останніх змін вище за течією:
(з нової особливості-123)
$ git master rebase

майстер A --- B --- C --- D --- E --- F
                            \
новахарактеристика-123 M --- N --- O


Я хочу знати, як зробити те ж саме в Mercurial, і я шукав відповідь в Інтернеті, але найкраще, що я міг знайти, це: git rebase - може Hg зробити це

Це посилання містить 2 приклади:
1. Я визнаю, що це: (замінюючи редакції з прикладу на ті, що є з мого власного прикладу)

hg вгору -CF  
hg гілка -f newfeature-123  
hg трансплантація -a -b новахарактеристика-123 

Не надто погано, за винятком того, що він залишає позаду попередньої рестарації MNO у вигляді нерозподіленої головки та створює 3 нові коміти M ', N', O ', які представляють їх, відгалужуючи оновлений магістраль.

В основному проблема полягає в тому, що я закінчую це:

майстер A --- B --- C --- D --- E --- F
                \ \
новафункція-123 \ M '--- N' --- O "
                  \
новахарактеристика-123 M --- N --- O

це не добре, оскільки воно залишає після себе місцеві, небажані вчинки, які слід відмовитися.

  1. Інший варіант із того ж посилання є
hg qimport -r M: O
hg qpop -a
hg вгору F
hg гілка newfeature-123
hg qpush -a
hg qdel -r qbase: qtip

і це призводить до отримання потрібного графіка:

майстер A --- B --- C --- D --- E --- F
                            \
новахарактеристика-123 M --- N --- O

але ці команди (всі 6!) здаються набагато складнішими, ніж

$ git master rebase

Я хочу знати, чи це єдиний еквівалент Hg, чи є інший доступний спосіб, такий як Git.


7
"Це не добре, оскільки воно залишає поза місцевими, небажані зобов'язання, які слід відмовитися". - власне, git робить те саме. Він не змінює і не видаляє комітети в початковій гілці, він просто вносить нові, які застосовують той самий набір змін у верхній частині головного. Ви все ще можете отримати доступ до старих за допомогою, git reflogі вони повністю не зникли, поки не збирають сміття. Якщо ви хочете зберегти їх у названій гілці, щоб вам не довелося використовувати рефлог, просто зробіть їх git branch feature-123_originalперед повторним виданням .
MatrixFrog

5
Випадкове запитання: ви самостійно малювали набори змін / гілок чи є інструмент, який це робить?
Амір Рахум

2
Просто зробив їх сам, коли TextWrangler встановив "перезапис".
jpswain

Відповіді:


235

VonC має відповідь, яку ви шукаєте , розширення Rebase. Однак варто витратити секунду-дві на роздуми над тим, чому ні mq, ні перезавантаження не включені за замовчуванням у mercurial: тому що mercurial - це все для незмінних наборів змін. Коли я працюю так, як ви описуєте, що майже щодня, ось такий шаблон:

1. Start working on a new feature:
$ hg clone mainline-repo newfeature-123
do a few commits (M, N, O)

master A---B---C
                \
newfeature-123   M---N---O

2. Pull new changes from upstream mainline:
$ hg pull

master A---B---C---D---E---F
                \
newfeature-123   M---N---O

3. merge master into my clone so that my new feature 
can be developed against the latest upstream changes:
(from newfeature-123)
$ hg merge F

master A---B---C---D---E---F
                \           \
newfeature-123   M---N---O---P

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

Тепер переходьте до відповіді VonC, коли я відкладаю свою мильну скриньку. :)


18
Примітка: поза курсом, Git не дозволяє точно переписати історію, лише легко створити нову ( utcc.utoronto.ca/~cks/space/blog/tech/GitNewHistory ). Додавши RebaseExtension, Mercurial надає той же самий зручний спосіб заміни старої історії на нову. Чому? Оскільки злиття не завжди є правильною відповіддю, особливо коли ваш набір змін слід розглядати як еволюцію на вершині F, а не на зворотному (P злився поверх O)
VonC

19
VonC, я згоден, злиття не завжди є правильним вибором, але я думаю, що різниця полягає в тому, що хочеться, щоб історія VCS була здатна розповісти їм. Я думаю, що історія завжди повинна відповідати на запитання на кшталт "Що це було, я спробував інтегрувати її спочатку, що не вийшло, і я вважав, що на той час це марно". Вчені ведуть журнали в ручці з пронумерованими сторінками, а інженери програмного забезпечення AFAIC повинні зберігати кожен байт, який вони коли-небудь набирали. Переписуючи історію, навіть відмінюйте вихід, але, безумовно, згортати розширення, HistEdit тощо. Це зовсім питання особистого вибору.
Bra4 Ry4an Brase

14
+1 для особистого вибору. Отже, з Git я використовую rebase для тривіальних розбіжностей і злиття для нетривіальних. Це дозволяє мені зберегти історію злиття, де я вважаю, що це важливо, але зберігати журнал чистим та лінійним більшу частину часу.
Кос

16
Також я роблю безліч інтерактивних знижок, тому що я схильний спочатку робити багато невеликих комісій, потім приєднуватися, розміщувати їх та прибирати, а потім об'єднувати їх з основною гілкою (або перезавантажувати поверх). Мені подобається, що кодування та управління змінами є окремими кроками.
Кос

6
Філософія "зберегти кожен байт по шляху розвитку" не дуже підходить для великих проектів з відкритим кодом, де дописувачі пропонують набір виправлень, а потім переробляють їх на основі зворотного зв’язку з обслуговуючими особами. Тоді в кінцевому підсумку основний сховище проекту має лише належну версію всіх змін, з усіма пов'язаними змінами в одному комітеті. інтерактивна база даних git дійсно хороша для очищення робочих змін у послідовності комітетів, які не залишають дерево зламаним, та повідомленнями фіксації, що відображають те, що ви вирішите сказати, коли ви закінчите роботу над усією справою.
Пітер Кордес

104

Ви можете шукати розширення Rebase . (реалізовано в рамках SummerOfCode 2008 )

У цих випадках може бути корисно "від'єднати" локальні зміни, синхронізувати сховище з основним потоком і потім додати приватні зміни поверх нових віддалених змін. Ця операція називається rebase.

Отримання :

alt текст

до:

alt текст


Як прокоментував нижче по steprobe :

У випадку, коли ви не втягуєте зміни, і у вас є дві гілки в репо, ви можете зробити ( використовуючиkeepbranches ):

hg up newfeature-123 
hg rebase -d master --keepbranches

( --keepbranches: Успадкуйте оригінальну назву гілки.)

Мохка згадує:

Мені подобається використовувати hg rebase --source {L1's-sha} --dest {R2's-sha}, але я не знав, що можу додати --keepbranchesв кінці.

Як показано нижче на Jonathan Blackburn :

 hg rebase -d default --keepbranches

1
Я переглянув розширення Rebase, але мені це все одно не зрозуміло. Чи можете ви поясніть, будь ласка, кроки для виконання того, що я описав вище?
jpswain

6
У тому випадку , коли ви не витягати зміни, і у вас є дві гілки в вашому репо, ви можете зробити: а hg up newfeature-123потімhg rebase -d master --keepbranches
steprobe

2
Я вважаю, що з базою даних нічого поганого немає, це лише питання вибору. Проблема полягає в тому, що ребазу зловживають, і я з @ Ry4an на цьому не переписую історію, щоб ви могли знати, що відбувається і коли.
Хорхе Варгас

@steprobe: дякую за підказку щодо використання --keepbranches. Мені подобається використовувати hg rebase --source {L1's-sha} --dest {R2's-sha}, але я не знав, що можу додати --keepbranchesв кінці. Про це згадується в інших відповідях нижчого рейтингу, але було б непогано написати це також відповідь.
Мойка

@Mojca Немає проблем. Відповідь я відредагував відповідно.
VonC

44

Припускаючи, що у вас є сучасна установка Hg, ви можете просто додати:

[extensions]
rebase = 

до ~ / .hgrc.

Потім ви можете використовувати команди hg rebase, hg pull --rebaseабо hg help rebase.


2
Просто додати до цього терміну команди, яку вам потрібно виконати, було б: hg rebase -s o -d f
Simple-Solution

21

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

Скажімо, я починаю з цього графіка (згенерований за допомогою розширення graphlog. Серйозна любов до викладачів).

@  9a4c0eb66429 Feature 3 commit 2 tip feature3
|
| o  af630ccb4a80 default againagainagain  
| |
o |  98bdde5d2185 Feature 3 branch commit 1  feature3
|/
o  e9f850ac41da foo   

Якщо я перебуваю на гілці особливостей3 і хочу відновити її за межі зобов’язання againagainagain, я розумію, що я би запускався hg rebase -d default. Це має такий результат:

@  89dada24591e Feature 3 commit 2 tip 
|
o  77dcce88786d Feature 3 branch commit 1  
|
o  af630ccb4a80 default againagainagain  
|
o  e9f850ac41da foo  

Місію виконано? Я не думаю, що так. Проблема полягає в тому, що коли комісії в гілці feature3 були перезавантажені на againagainagain, гілка feature3 була видалена . Мої комітети були переміщені до гілки за замовчуванням, чого я намагався уникати в першу чергу.

У Git результат виглядатиме так:

@  9a4c0eb66429 Feature 3 commit 2 tip
|
o  98bdde5d2185 Feature 3 branch commit 1 **feature3**
|
o  af630ccb4a80 default againagainagain
|
o  e9f850ac41da foo

Зауважте, що гілка особливості3 все ще існує, два коміти все ще знаходяться на гілці функцій3 і не видно за замовчуванням. Не зберігаючи гілки завдань, я не бачу, наскільки це функціонально відрізняється від злиття.

ОНОВЛЕННЯ : Я виявив --keepbranchesпрапор, підтримуваний hg rebase, і я радий повідомити, що все є okey-dokey. Використовуючи hg rebase -d default --keepbranches, я точно повторюю поведінку Git, якої я прагнув. Кілька псевдонімів пізніше, і я відмовляюся, як ні в кого справа.


7
Щойно виявили прапор --keepbranches на ребазі. Проблема вирішена. Якщо це був мій код, я зробив би це за замовчуванням, але це тільки я.
Джонатан Блекберн

1
Думаю, було б корисно, якби ви додали цю інформацію трохи у свою відповідь вище - знадобилося трохи часу, щоб її знайти.
HansMari

3

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

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

Сторінка дописувачів x265 пояснює, як повторно здійснити набір змін, над якими ви працюєте, щоб підготувати їх до подання в проект x265. (У тому числі використання TortoiseHG для внесення деяких, але не всіх змін в окремому файлі, наприклад, етап / нестабільність git gui diff hunk для фіксації).

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

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

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