Git diff - лише ім'я та скопіюйте цей список


151

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

git diff -–name-only commit1 commit2 > /path/to/my/file

Але що мені писати, якщо я хочу скопіювати всі перераховані файли в інше місце? І мені потрібна абсолютно однакова структура каталогів для скопійованих файлів.

Наприклад, я змінив і додав файли:

/protected/texts/file1.txt
/protected/scripts/index.php
/public/pics/pic1.png

Я хочу мати /home/changes/всі змінені та додані файли:

/home/changes/protected/texts/file1.txt
/home/changes/protected/scripts/index.php
/home/changes/public/pics/pic1.png

1
я не зовсім розумію, чого ви намагаєтесь досягти ... поширюючи зміни в різних клонах? створення патчів? виправлення файлів поза сховищем git?
knittl

Не патч, а точна структура копії змінених файлів. Як патч, але з солідними файлами
BazZy

І так, виправлення файлів за межами сховища git - найближча ціль для мене :)
BazZy

3
вибачте. ЩО? Ви хочете зафіксувати та повторно змінити файли та зміни дерев? це патч. git format-patchможе це зробити для діапазонів фіксації.
knittl

1
git diff commit1 commit2 > my.patchа потім cd other/path; patch -p1 < my.patch. Чому це потрібно робити з повною копією файлів? Якщо це, тому що ви думаєте, що патч може не застосовуватися, і тому інший каталог насправді не знаходиться в commit1штаті, вам дійсно слід скопіювати все з commit2штату ...
Cascabel

Відповіді:


118

Спробуйте наступну команду, яку я перевірив:

$ cp -pv --parents $(git diff --name-only) DESTINATION-DIRECTORY

2
Дякую за cp --parentsпідказку, я хотів цього варіанту роками і ніколи не знав, що він існує! ..очевидно, що я ніколи не намагався його шукати = \
Стефан Геннінгсен

2
Зауважте, що це не працює на Mac, оскільки --parentsопція cpнедоступна.
М. Джастін

Якісь поради щодо його використання, якщо файли мають незвичні символи? Пробіли, нордичні символи.
Halvor Holsten Strand

@HalvorStrand, я ще не тестував це, але налаштування IFS=$'\n'спочатку може зробити це. (Переважно в нижній частині, щоб не зіпсувати початкове значення IFS.)
Wildcard

Я отримую помилку cp: cannot stat 'git diff --name-only': No such file or directoryв git bash на Windows. Що я роблю неправильно? Довідник-каталог існує
Шива

14

Наступне має працювати добре:

git diff -z --name-only commit1 commit2 | xargs -0 -IREPLACE rsync -aR REPLACE /home/changes/protected/

Щоб пояснити далі:

  • " -zTo with" git diff --name-onlyозначає вивести список файлів, розділених байтами NUL замість нових рядків, на випадок, якщо ваші імена файлів мають у них незвичні символи.

  • The -0to xargssay для інтерпретації стандартного введення як розділений NUL список параметрів.

  • -IREPLACEПотрібно , так як за замовчуванням xargsбуде додавати параметри в кінці rsyncкоманди. Натомість, це говорить, щоб помістити їх там, де пізніше REPLACE. (Це прекрасна порада з цієї відповіді про помилку сервера .)

  • -aПараметр rsyncкошти для збереження права, права власності тощо , якщо це можливо. Засіб -Rвикористовувати повний відносний шлях при створенні файлів у пункті призначення.

Оновлення: якщо у вас є стара версія версії xargs, вам потрібно буде використовувати цю -iопцію замість -I. (Перша застаріла в пізніших версіях findutils.)


Це дивно - яку операційну систему ви використовуєте? Якщо це дистрибутив Linux, то який, і що це xargs --versionговорить?
Марк Лонгейр

1
Ах, у тій версії xargs, яку ви повинні використовувати -iзамість цього, яка застаріла в наступних версіях - 4.1 зараз досить стара. Я оновлю свою відповідь.
Марк Лонгейр

@Mark: Я пам’ятаю, що десь читав, що вам потрібно пробіл -Iу деяких версіях, тому, можливо, спробуйте -I REPLACEзамість цього.
Мікель

Не звертай уваги. Це теж не працює. -Iпідтримується лише з findutils4.2.10, випущений у грудні 2004 р.
Mikel

Ви повинні додати, --diff-filter=dщоб виключити видалені файли зі списку. Інакше ви отримаєте помилки під час спроби скопіювати їх у папку змін. Інакше чудова відповідь. Дякую!
тайм

11

Ось один вкладиш:

Перерахуйте змінені файли та запакуйте їх як * .zip:

git diff --name-only | zip patched.zip -@

Список останніх змінених файлів і запакуйте їх як * .zip:

git diff --name-only HEAD~ HEAD | zip patched.zip -@

Якщо ви використовуєте Windows, ви можете завантажити zip з командної
лінії

@ Radon8472 Що встановлюється sed.exe? Я все ще zipне знайду на вікнах.
Шива

ні, посилання вказує на завантаження для zip.exe не для sed. Якщо ви не можете використовувати zip в командному рядку, вам слід додати папку, де встановлено zip.exe, до PATHзмінної env.
Radon8472



2

Це прекрасно працює.

git diff 1526043 82a4f7d --name-only | xargs zip update.zip

git diff 1526043 82a4f7d --name-only |xargs -n 10 zip update.zip

1

Ніхто не згадав, cpioякий легко набрати, створює жорсткі посилання та обробляє пробіли у іменах:

git diff --name-only $from..$to  | cpio -pld outdir
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.