Чи можу я отримати сумісний з патчем вихід з git-diff?


160

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

$ git diff > before
$ git diff something_here > save.patch
$ git checkout . 
$ patch < save.patch
$ git diff > after
$ diff before after
$

З something_here порожнім він майже працює, але назви файлів неправильно. Я думаю, що я просто пропускаю якийсь варіант.

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

Відредагуйте мою провину тут, коли я задав неправильне запитання. Справжнє питання полягає в тому, що я хочу зберегти зміни, зробити об’єднання, а потім повторно застосувати зміни, якщо це можливо? Я запитав це неправильно, тому що я звик використовувати патч для вирішення подібних проблем і git diffвиглядав так, що саме цього я хотів зробити.

Чарльз Бейлі коментар був правильну відповідь. Для мене git-apply - це правильна річ (git-stash виглядає вагомішою, ніж мені потрібно. Перезавантаження, а пачки, безумовно, перевищують мій поточний рівень навичок.) Я прийму відповідь, яку дав Чарльз (тому що ти не можу прийняти коментар). Дякую за всі пропозиції.

Редагувати, 6 років потому Як кожен, хто знайомий з темою, знає, я переоцінив труднощі git stash. Приблизно щодня або близько того, я буду використовувати наступну послідовність:

$ git stash
$ git merge
$ git stash pop

8
Чи є якась причина, яку ви конкретно хочете використовувати, patchа не git apply?
CB Bailey

3
І навіть тоді вам справді потрібні патчі, а не щось подібне git stashчи інші інструменти для git?
CB Bailey

3
Після редагування, я думаю, що git stashце найпростіше рішення для того, що ви намагаєтеся зробити, але існує маса підходів, які працюють.
CB Bailey

1
@Malvolio: Дійсно, вам навіть не потрібно думати про тимчасове ім’я файлу, щоб зберігати свій патч.
CB Bailey

4
@Charlse, іноді потрібно надіслати патч комусь без усього сховища git. Наприклад, якщо використовується git-svn.
Елазар Лейбович

Відповіді:


139

Якщо ви хочете використовувати патч, вам потрібно видалити a/ b/префікси, якими користується git за замовчуванням. Це можна зробити за допомогою --no-prefixпараметра (ви також можете зробити це за допомогою -pпараметра патча ):

git diff --no-prefix [<other git-diff arguments>]

Однак, як правило, простіше використовувати прямі, git diffа потім використовувати вихід для подачі git apply.

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

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

# save uncommitted changes
git stash

# do a merge or some other operation
git merge some-branch

# re-apply changes, removing stash if successful
# (you may be asked to resolve conflicts).
git stash pop

7
git diff --no-prefix master > diff.patchа потімgit checkout master patch -p0 < diff.patch
Натім

1
@Natim Для максимальної безпеки я рекомендую використовувати patch --dry-run < diff.patchперед тим, як видавати останню команду.
ᴠɪɴᴄᴇɴᴛ

1
@ ᴠɪɴᴄᴇɴᴛ яка б користь від цього? Оскільки ми використовуємо git, ми навряд чи щось втратимо, чи не так?
Natim

1
@Natim Як я вже говорив, просто для максимальної безпеки не потрібно нічого скасовувати у разі помилки. Я також думав про людей, які читають це і хочуть використовувати patchпоза git (можливо, використовуючи патч-файл, сформований diff) у більш загальному випадку використання.
1616

Для включення нових файлів у свій патч потрібно також включити до патчу "git diff --no-prefix --cached". Може, є кращий спосіб?
джамшид

219

Просто використовуйте -p1: -p0у --no-prefixбудь-якому випадку вам потрібно буде скористатися справою, тому ви можете просто залишити --no-prefixта використовувати -p1:

$ git diff > save.patch
$ patch -p1 < save.patch

$ git diff --no-prefix > save.patch
$ patch -p0 < save.patch

1
Якщо вам цікаво, чому, чоловік документує це красиво - джерело .
tutuDajuju

3
Це не працюватиме з перейменами; git diffвиводить рядок, який patchігнорує. git applyце шлях.
hraban

17

У git diff є додатковий сегмент контуру, який є привабливим до файлових шляхів. Ви можете зняти цей запис у шляху, вказавши -p1 з патчем, наприклад:

patch -p1 < save.patch

10
  1. Я зберігаю diff поточного каталогу (включаючи непослані файли) проти поточної HEAD.
  2. Потім ви можете транспортувати save.patchфайл куди завгодно (включаючи двійкові файли).
  3. На своїй цільовій машині застосуйте виправлення за допомогою git apply <file>

Примітка: вона також відрізняється від поточно встановлених файлів.

$ git diff --binary --staged HEAD > save.patch
$ git reset --hard
$ <transport it>
$ git apply save.patch

Хахаха. Забавно. Я поставив це питання майже чотири роки тому, і як я це робив, еволюціонувало, але якби ви вчора запитали мене, як це зробити, я би дав вашу відповідь і сказав, що отримав це з відповідей на це питання. (Насправді я б, мабуть, використовував голий git diff > save.patchі git checkout .замість скидання, але так ...
Мальволіо

О, не помітив його 4 років: P. Btw, скидання полягає лише в тому, щоб продемонструвати, що він працює. Я також не бачу, щоб хто використовував git applyабо робив різницю, що стосується вашого стану та вказівника на останнє доступне введення. Учинок просто git diffнічого не зробив
Матей

Так, зараз мені цікаво, як я дізнався про це git apply. Справа в git diffтому, що я (думаю) використовувати git reset- співвідношення між репо, індексом та робочою зоною є проблемою.
Мальволіо

8

Корисний трюк, щоб уникнути створення тимчасових файлів патчів:

git diff | patch -p1 -d [dst-dir]

Саме те, що я хотів. Також чудово справляється зі сташами! git stash show -p stash@{3} | patch -p1 -d [dst-dir]
dtmland
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.