Làm thế nào để có được chỉ một tập tin từ một chi nhánh khác


1267

Tôi đang sử dụng git và làm việc trên nhánh chính. Chi nhánh này có một tập tin gọi là app.js.

Tôi có một experimentchi nhánh trong đó tôi đã thực hiện một loạt các thay đổi và hàng tấn cam kết. Bây giờ tôi muốn mang lại cho tất cả các thay đổi được thực hiện duy nhất app.jstừ experimentđến masterchi nhánh.

Làm thế nào để làm điều đó?

Một lần nữa tôi không muốn hợp nhất. Tôi chỉ muốn mang tất cả các thay đổi app.jstừ experimentchi nhánh sangmaster chi nhánh khác.



1
Ngoại trừ câu trả lời và những người khác cho đến ngày hôm nay trả lời cách sao chép nội dung của tệp, đó là điều tôi muốn khi tìm thấy nó. Tuy nhiên, nếu đọc chính xác, Nick muốn mang lại các thay đổi, không phải toàn văn và tệp trong mastercó thể phân kỳ từ experiment, ví dụ: có thể chứa các thay đổi được hợp nhất từ ​​các nhánh khác sẽ bị mất trong tệp chỉ được sao chép. Mặt khác, PS không muốn hợp nhất, nhưng theo tôi biết git mergethuật ngữ chỉ dành cho chi nhánh, không phải cho tệp cụ thể, vì vậy không có mâu thuẫn ở đây.
Alexei Martianov

Câu trả lời:


1605
git checkout master               # first get back to master
git checkout experiment -- app.js # then copy the version of app.js 
                                  # from branch "experiment"

Xem thêm git làm thế nào để hoàn tác các thay đổi của một tập tin?


Cập nhật tháng 8 năm 2019, Git 2.23

Với lệnh mới git switchgit restorelệnh, đó sẽ là:

git switch master
git restore -s experiment -- app.js

Theo mặc định, chỉ có cây làm việc được khôi phục.
Nếu bạn cũng muốn cập nhật chỉ mục (nghĩa là khôi phục nội dung tệp thêm nó vào chỉ mục trong một lệnh):

git restore -s experiment --staged --worktree -- app.js
# shorter:
git restore -s experiment -WS -- app.js

Như Jakub Narębski đề cập trong các bình luận:

git show experiment:path/to/app.js > path/to/app.js

cũng hoạt động, ngoại trừ, như chi tiết trong câu hỏi SO " Làm cách nào để truy xuất một tệp từ sửa đổi cụ thể trong Git? ", bạn cần sử dụng đường dẫn đầy đủ từ thư mục gốc của repo.
Do đó, đường dẫn / đến / app.js được Jakub sử dụng trong ví dụ của mình.

Như Frosty đề cập trong bình luận:

bạn sẽ chỉ nhận được trạng thái gần đây nhất của app.js

Nhưng, cho git checkouthoặc git show, bạn thực sự có thể tham khảo bất kỳ sửa đổi nào bạn muốn, như được minh họa trong câu hỏi SO " sửa đổi kiểm tra git của một tệp trong git gui ":

$ git show $REVISION:$FILENAME
$ git checkout $REVISION -- $FILENAME

sẽ giống nhau là $ FILENAME là một đường dẫn đầy đủ của một tệp được phiên bản.

$REVISIONcó thể được hiển thị trong git rev-parse:

experiment@{yesterday}:app.js # app.js as it was yesterday 
experiment^:app.js            # app.js on the first commit parent
experiment@{2}:app.js         # app.js two commits ago

và như thế.

schmijos thêm vào trong các ý kiến :

bạn cũng có thể làm điều này từ một stash:

git checkout stash -- app.js

Điều này rất hữu ích nếu bạn đang làm việc trên hai chi nhánh và không muốn cam kết.


13
Một lưu ý: bạn sẽ chỉ nhận được trạng thái gần đây nhất của app.js, bạn sẽ không nhận được bất kỳ lịch sử nào được chuyển từ nhánh thử nghiệm.
Frosty

2
@ThomasReggi bạn sẽ có thể nhập (thanh toán) một tệp từ bất kỳ chi nhánh nào đến bất kỳ chi nhánh hiện tại nào. Nếu bạn không thể, đó có thể là một câu hỏi hay để hỏi ở đây, với các chi tiết cụ thể như thông báo lỗi chính xác và phiên bản Git và HĐH được sử dụng.
VonC

2
Trong một thư mục con, bạn cũng có thể sử dụng experiment:./app.js. (Bạn không phải chỉ định đường dẫn đầy đủ.) Tôi đã học được điều này nhờ vào thông báo lỗi rất hữu ích mà git đã đưa cho tôi: "Ý bạn là 'mybranch: full / path / to / my / file.xsl' aka 'mybranch: ./file.xsl '? " Vâng, tôi đã làm! Tôi không nghĩ rằng tôi đã từng rất vui mừng bởi một thông báo lỗi nghiêm trọng.
Evan Lenz

1
@TomaszGandor Vâng, tôi đề cập rằng trong stackoverflow.com/a/21066361/6309 , trong đó git show sẽ không sửa đổi chỉ mục, nhưng git checkout sẽ sửa đổi chỉ mục.
VonC

1
@FriedBrice Xem câu trả lời của tôi: những ngày này, nó sẽ làgit restore -s new-feature path/to/app.js
VonC

360

Mọi thứ đơn giản hơn nhiều, hãy sử dụng git checkout cho điều đó.

Giả sử you're on masterchi nhánh, để có được app.js from new-featurechi nhánh làm:

git checkout new-feature path/to/app.js

// note that there is no leading slash in the path!

Điều này sẽ mang lại cho bạn nội dung của tập tin mong muốn. Như mọi khi, bạn có thể sử dụng một phần của sha1 thay vì tên nhánh tính năng mới để lấy tệp như trong cam kết cụ thể đó.

Lưu ý : new-featurecần phải là một chi nhánh địa phương , không phải là một chi nhánh từ xa.


77
Tôi thấy hữu ích khi luôn chỉ định nguồn gốc git checkout origin/source_branch path/to/filevì nếu bạn bỏ qua việc cập nhật nhánh nguồn của repo cục bộ, bạn có thể nhận được một phiên bản cũ của tệp ... Hãy hỏi tôi làm sao tôi biết. ;)
talyric

3
@Mymozaaa câu hỏi không đề cập đến điều khiển từ xa, do đó, giả định rằng đó là một repo hoàn toàn cục bộ
Dmitry Avtonomov

1
Lệnh này sẽ mang lại lịch sử của tệp hay chỉ là phiên bản cuối cùng của tệp?
dùng1366265

1
@ user1366265 Lệnh này sẽ đặt tệp như trong cam kết cụ thể mà bạn chỉ định hoặc người đứng đầu chi nhánh bạn chỉ định. Không có thứ gọi là "lịch sử của một tập tin", tất cả thông tin lịch sử chỉ được lưu trữ trong các chi nhánh.
Dmitry Avtonomov

3
Điều này dường như tự động giai đoạn các tập tin kiểm xuất. Có thể làm như vậy mà không cần dàn dựng?
bluenote10

44
git checkout branch_name file_name

Thí dụ:

git checkout master App.java

Điều này sẽ không hoạt động nếu tên chi nhánh của bạn có một khoảng thời gian trong đó.

git checkout "fix.june" alive.html
error: pathspec 'fix.june' did not match any file(s) known to git.

@PhilipRego Câu trả lời này là chính xác. Tôi đoán có cách viết hoa hoặc dấu câu khác nhau trong chi nhánh của bạn hoặc bạn chỉ có một chi nhánh ở xa chứ không phải chi nhánh địa phương. Xem tài liệu kiểm tra git: git-scm.com/docs/git-checkout#Documentation/ Kẻ
Bret

@Bret Tôi thấy nó không hoạt động khi tên chi nhánh có dấu chấm. Tôi đề nghị chỉnh sửa
Philip Rego

Đây là câu trả lời tốt nhất. Tôi muốn câu trả lời này được đánh giá cao nhất. Cái cao nhất hiện tại rất khó hiểu và không đơn giản
Russell Lego

41

Bổ sung cho câu trả lời của VonC và chhh.

git show experiment:path/to/relative/app.js > app.js
# If your current working directory is relative than just use
git show experiment:app.js > app.js

hoặc là

git checkout experiment -- app.js

2
Mát mẻ! Tôi ghét chỉ định những con đường dài. Là dấu gạch ngang kép ( --) giữa tên nhánh và đường dẫn tùy chọn? Có phải chỉ để ngăn chặn các đường dẫn, bắt đầu bằng dấu gạch ngang, không được coi là tùy chọn / công tắc?
Tomasz Gandor

Thành thật mà nói tôi không biết. Tôi thậm chí không nhận thấy rằng tôi đã quên dấu gạch ngang đôi cho đến khi bạn chỉ ra điều này.
AlexLordThorsen

6
@TomaszGandor Đây --là tùy chọn, nhưng sẽ hữu ích hơn để tránh xung đột với tên chi nhánh. Ví dụ: git checkout -- foocó nghĩa là "kiểm tra tệp foo từ HEAD" (nghĩa là ghi đè các thay đổi cục bộ trong foo , tức là một tập hợp con git reset --hard), nhưng git checkout foocó thể có nghĩa là hoặc "hãy đi đến nhánh foo ".
Alois Mahdal

8

Hoặc nếu bạn muốn tất cả các tệp từ một chi nhánh khác:

git checkout <branch name> -- .

24
Queston ban đầu chứa "chỉ một tệp".
greatvovan

1
điều này thay thế các tệp hiện có thay vì hợp nhất
Amare

3
Điều này .tạo ra một sự khác biệt lớn: thay vì chuyển sang một chi nhánh khác, nó sao chép tất cả các tệp từ đó trong khi vẫn để bạn ở trên hiện tại. Bạn nhận được nội dung từ chi nhánh khác mà không đi vào nó.
Xeverous

4

Xem lại tệp trên github và kéo nó từ đó

Đây là một cách tiếp cận thực tế không trực tiếp trả lời OP, nhưng một số đã thấy hữu ích:

Nếu nhánh được đề cập là trên GitHub, thì bạn có thể điều hướng đến nhánh và tệp mong muốn bằng bất kỳ công cụ nào mà GitHub cung cấp, sau đó nhấp vào 'Nguyên' để xem văn bản đơn giản, và (tùy chọn) sao chép và dán văn bản dưới dạng mong muốn.

Tôi thích cách tiếp cận này vì nó cho phép bạn xem toàn bộ tệp từ xa trước khi kéo nó vào máy cục bộ của bạn.


2
Tuy nhiên, sao chép và dán tệp thô có thể gây ra thay đổi ký tự không mong muốn trong git diff của bạn. Sẽ an toàn hơn khi lưu tệp trực tiếp vào dự án của bạn để đảm bảo không có thay đổi.
Philip Rego

0

Nếu bạn muốn tệp từ một cam kết cụ thể (bất kỳ chi nhánh nào), hãy nói 06f8251f

kiểm tra git 06f8251f path_to_file

ví dụ: trong windows:

kiểm tra git 06f8251f C: \ A \ B \ C \ D \ file.h


1
Cảm ơn đã dành thời gian trả lời! Nhưng điều này không trả lời câu hỏi, và một câu trả lời hay mà rất đáng ghét đã được đăng 9 năm trước. Không cần phải trả lời câu hỏi.
Nathan

Đây là một kịch bản thực tế hợp lệ. Câu trả lời giao dịch chính xác với chi nhánh, nhưng những gì về việc xem xét một cam kết cụ thể của chi nhánh.
arupjbasu

0

Một cách khác là tạo một bản vá với sự khác biệt và áp dụng nó trong nhánh chính. Giả sử cam kết cuối cùng trước khi bạn bắt đầu làm việc trên app.js là 00000aaaaa và cam kết chống lại phiên bản bạn muốn là 00000bbbbb

Bạn chạy cái này trên nhánh thử nghiệm:

git diff 00000aaaaa 00000bbbbb app.js > ~/app_changes.git

Điều này sẽ tạo một tệp có tất cả sự khác biệt giữa hai cam kết đó cho app.js mà bạn có thể áp dụng bất cứ nơi nào bạn muốn. Bạn có thể giữ tập tin đó ở bất cứ đâu ngoài dự án

Sau đó, trong chủ bạn chỉ cần chạy:

git apply ~/app_changes.git

bây giờ bạn sẽ thấy những thay đổi trong các dự án như thể bạn đã thực hiện chúng bằng tay.


-3
git checkout master               -go to the master branch first
git checkout <your-branch> -- <your-file> --copy your file data from your branch.

git show <your-branch>:path/to/<your-file> 

Hy vọng điều này sẽ giúp bạn. Xin vui lòng cho tôi biết nếu bạn có bất kỳ câu hỏi.

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.