FETCH_HEAD trong Git có nghĩa là gì?


220

git pull --help nói:

Trong chế độ mặc định của nó, git pulllà tốc ký cho git fetchtheo sau git merge FETCH_HEAD.

Đây là FETCH_HEADgì và những gì thực sự được hợp nhất trong thời gian này git pull?


3
Lưu ý: kể từ git 1.8.4 (tháng 8 năm 2013), git fetch origin mastersẽ thực sự cập nhật origin/master, không chỉ FETCH_HEAD. Xem stackoverflow.com/a/20967347/6309
VonC

Để biết thêm về git merge FETCH_HEAD(kể từ Git 2.5, quý 2 năm 2015), hãy xem stackoverflow.com/a/30425991/6309
VonC

Câu trả lời:


218

FETCH_HEADlà một giới thiệu ngắn hạn, để theo dõi những gì vừa được tìm nạp từ kho lưu trữ từ xa. git pullđầu tiên gọi git fetch, trong trường hợp bình thường lấy một nhánh từ xa; FETCH_HEADchỉ vào đầu của nhánh này (nó lưu SHA1 của cam kết, giống như các nhánh làm). git pullsau đó gọi git merge, sáp nhập FETCH_HEADvào chi nhánh hiện tại.

Kết quả là chính xác những gì bạn mong đợi: cam kết ở đầu nhánh từ xa thích hợp được hợp nhất vào cam kết ở đầu nhánh hiện tại của bạn.

Điều này giống như làm git fetchmà không cần đối số (hoặc git remote update), cập nhật tất cả các nhánh từ xa của bạn, sau đó chạy git merge origin/<branch>, nhưng sử dụng FETCH_HEADnội bộ thay vì tham chiếu bất kỳ tham chiếu đơn lẻ nào được tìm nạp, thay vì cần đặt tên cho mọi thứ.


9
@Jefromi: xin lỗi, tôi nghĩ bạn đã sai: theo như tôi hiểu, git fetchcập nhật (hợp nhất) tất cả dữ liệu đối tượng từ bộ lưu trữ từ xa, không chỉ là một bữa ăn trưa. Vì vậy, tôi không hiểu từ câu trả lời của bạn như thế nào git quyết định đến đỉnh của nhánh nào để chỉ FETCH_HEAD. Tôi cũng không thể tìm thấy FETCH_HEADtrong tài liệu git (định nghĩa, không phải ví dụ). Sự tồn tại của FETCH_HEADngoại hình đối với tôi giống như một cách giải quyết hơn, để làm cho git pullcông việc bằng cách nào đó .
Alexey

14
Alexey: FETCH_HEADtương ứng với đầu của nhánh từ xa được chỉ định bởi branch.<BRANCH>.mergetrong cấu hình kho lưu trữ cục bộ. Vì vậy, trong khi fetchthực sự tìm nạp tất cả dữ liệu đối tượng từ bộ lưu trữ từ xa, FETCH_HEADđược sử dụng để chỉ ra nơi nhánh từ xa được theo dõi bởi nhánh cục bộ đã tiến lên. Vì vậy, nếu bạn ở masternhánh cục bộ và chạy git fetch, và branch.master.mergetrỏ đến refs/heads/master, thì FETCH_HEADsẽ có cùng giá trị như origin/masterngay sau thao tác tìm nạp.
larsks

4
@alexy FETCH_HEAD được mô tả trong đoạn thứ hai của mô tả về git fetch trong trang man của nó. Câu trả lời của tôi là chính xác. Và git fetch không có đối số sẽ cập nhật tất cả các nhánh từ xa cho điều khiển từ xa mặc định ... nhưng điều này chắc chắn không giống như hợp nhất.
Cascabel

4
Điều gì là FETCH_HEADnếu bạn tìm nạp tất cả các chi nhánh từ xa thông qua git fetch -a?
stigi

2
@stigi Mẹo của nhánh theo dõi từ xa, nhánh thanh toán hiện tại của bạn đang trỏ đến trong cấu hình git. Xin vui lòng xem câu trả lời của larsks trong bình luận ở trên.
Ankur Agarwal

19

FETCH_HEAD là một tham chiếu đến mẹo của lần tìm nạp cuối cùng, cho dù việc tìm nạp đó được bắt đầu trực tiếp bằng cách sử dụng lệnh tìm nạp hay là một phần của thao tác kéo. Giá trị hiện tại của FETCH_HEAD được lưu trữ trong .gitthư mục trong một tệp có tên, bạn đoán nó , FETCH_HEAD.

Vì vậy, nếu tôi phát hành:

git fetch https://github.com/ryanmaxwell/Fragaria

FETCH_HEAD có thể chứa

3cfda7cfdcf9fb78b44d991f8470df56723658d3        https://github.com/ryanmaxwell/Fragaria

Nếu tôi có repo từ xa được định cấu hình là một nhánh theo dõi từ xa thì tôi có thể theo dõi tìm nạp của mình với sự hợp nhất của nhánh theo dõi. Nếu tôi không, tôi có thể hợp nhất mẹo tìm nạp cuối cùng trực tiếp bằng FETCH_HEAD.

git merge FETCH_HEAD

1
Để thêm 5 xu của tôi. Điều làm tôi bối rối là, FETCH_HEAD của tôi đứng sau các cam kết mới nhất, ngay cả khi thực hiện một lần tìm nạp mới trả về "không thay đổi" (trong nhật thực). Tôi nghĩ lý do là, tất cả những thay đổi kể từ lần tìm nạp cuối cùng của tôi là từ chính tôi và đã bị tôi đẩy lên máy chủ. Vì vậy, một lần tìm nạp tiếp theo không có gì để làm và thậm chí không cập nhật FETCH_HEAD. Tôi không chắc chắn nếu đây là một thiếu sót của việc thực hiện GIT hoặc Eclipse Git.
Torge

11

Như đã đề cập trong câu trả lời của Jonathan , FETCH_HEAD tương ứng với tệp .git/FETCH_HEAD. Thông thường, tệp sẽ trông như thế này:

71f026561ddb57063681109aadd0de5bac26ada9                        branch 'some-branch' of <remote URL>
669980e32769626587c5f3c45334fb81e5f44c34        not-for-merge   branch 'some-other-branch' of <remote URL>
b858c89278ab1469c71340eef8cf38cc4ef03fed        not-for-merge   branch 'yet-some-other-branch' of <remote URL>

Lưu ý làm thế nào tất cả các chi nhánh nhưng một được đánh dấu not-for-merge. Một trong những lẻ là chi nhánh đã được kiểm tra trước khi tìm nạp. Tóm lại: FETCH_HEAD về cơ bản tương ứng với phiên bản từ xa của chi nhánh hiện đang được kiểm tra.


9

Tôi vừa phát hiện và sử dụng FETCH_HEAD. Tôi muốn có một bản sao cục bộ của một số phần mềm từ máy chủ và tôi đã làm

git fetch gitserver release_1

gitserverlà tên của máy tôi lưu trữ kho git. release_1là một thẻ cho một phiên bản của phần mềm. Thật ngạc nhiên, release_1sau đó không tìm thấy ở đâu trên máy cục bộ của tôi. Tôi phải gõ

 git tag release_1 FETCH_HEAD 

để hoàn thành bản sao của chuỗi cam kết được gắn thẻ (phát hành_1) từ kho lưu trữ từ xa đến kho lưu trữ cục bộ. Fetch đã tìm thấy thẻ từ xa, sao chép cam kết vào máy cục bộ của tôi, không tạo thẻ cục bộ, nhưng đã đặt thành FETCH_HEADgiá trị của cam kết, để tôi có thể tìm và sử dụng nó. Sau đó tôi đã sử dụng FETCH_HEADđể tạo một thẻ cục bộ khớp với thẻ trên điều khiển từ xa. Đó là một minh họa thực tế về những gì FETCH_HEADvà làm thế nào nó có thể được sử dụng, và có thể hữu ích cho người khác tự hỏi tại sao git fetch không làm những gì bạn mong đợi một cách ngây thơ.

Theo tôi, tốt nhất nên tránh cho mục đích đó và cách tốt hơn để đạt được những gì tôi đang cố gắng làm là

git fetch gitserver release_1:release_1

tức là tìm nạp phiên bản_1 và gọi nó là phát hành_1 cục bộ. (Đây là nguồn: Dest, xem https://git-scm.com/book/en/v2/Git-Iternals-The-Refspec ; chỉ trong trường hợp bạn muốn đặt cho nó một tên khác!)

FETCH_HEADĐôi khi bạn có thể muốn sử dụng : -

git fetch gitserver bugfix1234
git cherry-pick FETCH_HEAD

có thể là một cách hay để sử dụng bản sửa lỗi số 1234 từ máy chủ Git của bạn và để bộ sưu tập rác của Git xử lý bản sao từ máy chủ sau khi bản sửa lỗi được chọn vào nhánh hiện tại của bạn. (Tôi giả sử rằng có một cam kết được gắn thẻ sạch đẹp chứa toàn bộ sửa lỗi trên máy chủ!)


Phản hồi thú vị. +1
VonC

Cảm ơn. Tôi đã chỉnh sửa bài viết gốc của mình, được viết khi lần đầu tiên tôi phát hiện ra FETCH_HEAD vài năm trước, vì nó xuất hiện để khuyến khích sao chép một thẻ bằng cách sử dụng FETCH_HEAD thay vì cú pháp nguồn: Dest cho các từ chối. Hy vọng rằng bây giờ tôi đã đưa ra một ví dụ tốt hơn về cách FETCH_HEAD có thể được sử dụng.
Ivan

3

git pull là sự kết hợp của một tìm nạp theo sau là một sự hợp nhất. Khi git fetch xảy ra, nó ghi chú cam kết của những gì nó đã tìm nạp trong FETCH_HEAD (chỉ một tệp có tên đó trong .git) Và những cam kết này sau đó được hợp nhất vào thư mục làm việc của bạn.


3
@manjold, ý của bạn là " cam kết về những gì nó đã tải"? Git tìm nạp mọi thứ với fetch.
Alexey

@Alexey từ hướng dẫn sử dụng git: git-scm.com/docs/git-fetch : Tên của các ref được tìm nạp, cùng với tên đối tượng mà chúng trỏ tới, được ghi vào .git / FETCH_HEAD
PJ_Finnegan
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.