Використовуючи GIT, як я можу вибірково об’єднувати зміни з одного коміту на інший “форк”?


81

Візьмімо цей сценарій:

  1. Я вирішую «розгалужити» кодову базу на github.com і починаю виконувати мою рутину: Редагувати - Фіксувати - Натискати; ака хак хак хак.
  2. Після того, як я вніс деякі зміни, я бачу деякі зміни, внесені іншою людиною у тому ж проекті, і вони мені подобаються!
  3. Я вирішую, що хочу об’єднати їх у свої. Проблема в тому, що я хочу лише "порцію" одного конкретного коміту з кількох комітів, які він зробив.

Який би був найефективніший спосіб отримати цю вибрану кількість змін, об’єднаних у мою «вилку»?



Можливий дублікат комітету з частковим збиранням вишні з Git
Inigo

Відповіді:


119

Провівши хвилі світу IRC, хтось дав чудове рішення:

git cherry-pick SHA1 --no-commit
git add --patch

Сподіваємось, це допоможе комусь ще з тим самим питанням!

EDIT: Добре, можливо, це не все так просто. Ось повні кроки:

  1. Спочатку ви повинні бути у своєму сховищі, виконати необхідне cd-ing, щоб перейти до робочого каталогу.

  2. Тепер потрібно додати віддалену гілку, а потім отримати її. Зробіть це за допомогою:

    git remote add someUser git://github.com/someUser/someRepo.git

    git fetch someUser

  3. Тепер ви можете запускати команди, такі як git log someUser/masterзнайти коміт SHA1, який ви хочете об'єднати в "частково".

  4. Після того, як у вас є SHA, тепер ви можете запустити:

    git cherry-pick -n SHA1

    де SHA1коміт SHA, так!

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

  6. Тепер вам доведеться скинути індекс до версії HEAD, після чого ви можете використовувати надійну add --patchкоманду GIT, щоб вибрати, які зміни ви хочете:

    git reset HEAD

    git add --patch або git add -p

  7. Ага! Час фіксації:

    git commit -m "I merged a select amount of changes"

  8. Щоб прибрати безлад (речі, яким ви сказали «ні» git add --patch) і зберегти лише вибрані зміни у вашому робочому сховищі, запустіть:

    git reset --hard HEAD

    Мабуть, git checkout -fце також інший варіант.


Я рада, що ви знайшли git add -p; це надзвичайно потужний. Якщо у вас вже є спірний коміт (наприклад, він не використовувався --no-commitв програмі cherry-pick, або це один із ваших комітів), ви можете використати git reset HEAD^для перемотування індексу коміту назад, а потім додати зміни назад у git add -p, виконуючи кроки . Якщо коміт не на кінчику гілки, ви можете скористатися git rebase -iредагуванням відповідного коміту та вибрати.
Cascabel

3
приємна прогулянка. пам’ятайте, якщо ви просто хочете всю фіксацію, ви просто -ngit cherry-pick SHA1
видаєте

Ключовий біт тут git remote add <user> <fork-url>- тоді ви можете git cherry-pickяк зазвичай.
Том

2

Мені незрозуміло, що ти хочеш. Якщо ви хочете залучити лише певні коміти з інших форків, ви можете використовувати git cherry-pick SHA. Повне пояснення щодо gitready .


Я лише після "частини" / "розділу" / "декількох рядків" одного конкретного коміту, об'єднаних у моє сховище. Не особливо конкретно для файлу.
Тім

У такому випадку, git format-patch SHA, git apply <patch> є опцією
hgmnz

2

Мені дуже подобається рішення Тіма, проте іноді мені подобається возитися у vimdiff. Моє рішення цієї проблеми є грубим, але воно працює для мене, тому що мені подобається vim.

У мене є vimdiff, встановлений як мій difftool, а потім для вибіркового об'єднання я розрізняю гілку:

git difftool <branch> <file>

Потім я переходжу на панель з поточною версією гілки і редагую оригінал у vim (іноді це не потрібно, але іноді vimdiff відкриває версію в / tmp) і вимикаю режим лише для читання:

:e <file>
:set readonly!

Тепер я можу використовувати інструменти виправлення vim, такі як doі, dpщоб застосовувати те, що я хочу, і робити інші невеликі редагування, коли я ходжу. Коли я закінчу, я зберігаю файл, виходжу з vim, а потім індексую і фіксую файл у git, як звичайне редагування.

Як я вже говорив, це не особливо складно, але воно дуже потужне, і все ще суто в командному рядку. Тільки не забудьте додати чітке повідомлення коміту, оскільки git не буде автоматично включати повідомлення злиття для вас.

приклад vimdiff http://j.mp/1dZVllt


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

1

Якщо вам потрібен лише порт коміту, вам, мабуть, краще за все вибрати комміт, який ви хочете, і скинути файли, до яких ви не хочете торкатися.

git cherry-pick SHA1
git checkout HEAD file1 file2 ... fileN

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


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