Git diff - chỉ tên và sao chép danh sách đó


151

Tôi chỉ muốn nhận một danh sách các tập tin thay đổi giữa hai phiên bản, rất đơn giản:

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

Nhưng, tôi nên viết gì, nếu tôi muốn sao chép tất cả các tệp được liệt kê sang nơi khác? Và tôi cần cấu trúc thư mục hoàn toàn giống hệt nhau cho các tập tin sao chép.

Ví dụ: tôi đã sửa đổi và thêm tệp:

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

Tôi muốn có trong /home/changes/tất cả những tập tin đã thay đổi và thêm vào:

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

1
Tôi hoàn toàn không hiểu những gì bạn đang cố gắng để đạt được những thay đổi lan truyền đến các bản sao khác nhau? tạo bản vá? vá các tập tin bên ngoài một kho lưu trữ git?
knittl

Không vá, nhưng cấu trúc sao chép chính xác của các tập tin thay đổi. Giống như bản vá, nhưng với các tệp vững chắc
BazZy

Và vâng, vá các tệp bên ngoài kho git - mục tiêu gần nhất với tôi :)
BazZy

3
lấy làm tiếc. GÌ? Bạn muốn chụp và phát lại các thay đổi đối với các tệp và thay đổi thành cây? đó là một bản vá. git format-patchcó thể làm điều này cho phạm vi cam kết.
knittl

1
git diff commit1 commit2 > my.patchvà sau đó cd other/path; patch -p1 < my.patch. Tại sao nó phải được thực hiện với các bản sao đầy đủ của các tập tin? Nếu đó là vì bạn nghĩ rằng bản vá có thể không áp dụng, và do đó thư mục khác không thực sự ở commit1trạng thái, bạn thực sự phải sao chép mọi thứ từ commit2trạng thái ...
Cascabel

Câu trả lời:


118

Hãy thử lệnh sau mà tôi đã kiểm tra:

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

2
Cảm ơn cp --parentsgợi ý, tôi đã muốn lựa chọn đó trong nhiều năm và không bao giờ biết nó tồn tại! .. rõ ràng tôi không bao giờ bận tâm để tìm kiếm nó = \
Stephan Henningsen

2
Lưu ý rằng điều này không hoạt động trên Mac, vì --parentstùy chọn cpkhông khả dụng.
M. Justin

Bất kỳ lời khuyên về việc sử dụng này nếu các tập tin có ký tự bất thường? Khoảng trắng, ký tự nordic.
Halvor Holsten Strand

@HalvorStrand, tôi chưa thử nó, nhưng đặt IFS=$'\n'trước có thể làm được. (Tốt nhất là trong một khung con để không làm xáo trộn giá trị IFS ban đầu của bạn.)
Wildcard

Tôi đang gặp lỗi cp: cannot stat 'git diff --name-only': No such file or directorytrên git bash trên windows. Tôi đang làm gì sai? Thư mục đích tồn tại
Shiva

14

Sau đây nên hoạt động tốt:

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

Để giải thích thêm:

  • Các -zto có git diff --name-onlynghĩa là xuất ra danh sách các tệp được phân tách bằng byte NUL thay vì dòng mới, chỉ trong trường hợp tên tệp của bạn có các ký tự khác thường trong đó.

  • Các -0để xargsnói để giải thích đầu vào tiêu chuẩn như một danh sách NUL-tách các thông số.

  • Điều -IREPLACEnày là cần thiết vì theo mặc định xargssẽ nối các tham số vào cuối rsynclệnh. Thay vào đó, điều đó nói rằng đặt chúng ở nơi sau REPLACEnày. (Đó là một mẹo hay từ câu trả lời Lỗi Máy chủ này .)

  • Các -atham số để rsyncphương tiện để bảo vệ quyền, quyền sở hữu, vv nếu có thể. Các -Rphương tiện để sử dụng đường dẫn tương đối đầy đủ khi tạo các tệp ở đích.

Cập nhật: nếu bạn có phiên bản cũ xargs, bạn sẽ cần sử dụng -itùy chọn thay vì -I. (Cái trước không dùng nữa trong các phiên bản sau củafindutils .)


Điều đó thật lạ - bạn đang sử dụng hệ điều hành nào? Nếu đó là một bản phân phối Linux, cái nào và cái gì xargs --versionnói?
Mark Longair

1
À, trong phiên bản xargs đó bạn cần sử dụng -ithay thế, cái này không được dùng trong các phiên bản sau - 4.1 bây giờ khá cũ. Tôi sẽ cập nhật câu trả lời của tôi.
Mark Longair

@Mark: Tôi nhớ đọc ở đâu đó rằng bạn cần một khoảng trống sau -Itrong một số phiên bản, vì vậy có thể thử -I REPLACEthay thế.
Mikel

Đừng bận tâm. Điều đó cũng không hoạt động. -Ichỉ được hỗ trợ kể từ findutils4.2.10, phát hành tháng 12 năm 2004.
Mikel

Bạn nên thêm --diff-filter=dđể loại trừ các tập tin bị xóa khỏi danh sách. Nếu không, bạn sẽ nhận được lỗi trong khi cố gắng sao chép chúng vào thư mục thay đổi. Nếu không thì trả lời tuyệt vời. Cảm ơn!
taymless 23/2/2017

11

Đây là một lót:

Liệt kê các tệp đã thay đổi và đóng gói chúng dưới dạng * .zip:

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

Liệt kê các tệp đã thay đổi cam kết cuối cùng và đóng gói chúng dưới dạng * .zip:

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

Nếu bạn đang sử dụng windows, bạn có thể tải xuống zip dòng lệnh từ sourceforge.net/projects/gnuwin32/files/zip
Radon8472

@ Radon8472 Cài đặt đó sed.exe? Tôi vẫn zipkhông tìm thấy trên các cửa sổ.
Shiva

không, liên kết đang trỏ đến tải xuống cho zip.exe không phải cho sed. Nếu bạn không thể sử dụng zip trong dòng lệnh, bạn nên thêm thư mục nơi zip.exe được cài đặt vào PATHbiến env của bạn .
Radon8472

6
zip update.zip $(git diff --name-only commit commit)


2

Nó hoạt động hoàn hảo.

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

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

1

Không ai đã đề cập đến cpioviệc dễ gõ, tạo liên kết cứng và xử lý khoảng trắng trong tên tệp:

git diff --name-only $from..$to  | cpio -pld outdir
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.