2013-02-22 36 views
12

Tôi rất mới với git và tôi gặp sự cố với thao tác đơn giản fetch.git fetch, FETCH_HEAD và origin/master

Tôi đang cố tìm nạp tiến trình của đồng nghiệp từ kho lưu trữ của anh ấy. Lúc đầu tôi đã làm git fetch HEAD mà nhắc git để tải về khoảng 350MB dữ liệu vì vậy tôi đã chắc chắn nó đã làm điều gì đó. Tuy nhiên, origin/master kết thúc vẫn chỉ đến cùng một cam kết cũ (thực sự nó dưới tên dev nhưng tôi sẽ gọi nó là master - anh ta không có một master).

Sau đó tôi đã thử git fetch origin master nhưng dường như không làm gì, nó chỉ cập nhật FETCH_HEAD. Tôi đã gắn thẻ cam kết FETCH_HEAD vì vậy tôi sẽ không mất nó, nhưng tôi vẫn muốn có một nhánh từ xa được cập nhật.

Điều gì đã xảy ra? Tôi không có quyền truy cập vào kho lưu trữ từ xa. Tôi vẫn có thể sửa nó ở nhà được không?

+0

là 'nguồn gốc' đồng nghiệp của bạn repo? –

+1

Lưu ý: Vì git 1.8.4 (tháng 8 năm 2013), bạn không nên ngạc nhiên hơn: 'git fetch origin master' sẽ cập nhật' origin/master'! Xem [câu trả lời của tôi dưới đây] (http://stackoverflow.com/a/20967347/6309) – VonC

+1

Liên quan: [FETCH_HEAD trong Git có nghĩa là gì?] (Http://stackoverflow.com/q/9237348/55075) tại SO – kenorb

Trả lời

13

Tôi hơi bối rối với các lệnh bạn sử dụng. HEAD thường là nhãn git sử dụng để theo dõi cam kết hiện đang nằm trong thư mục làm việc. Lệnh git fetch sẽ yêu cầu điều khiển từ xa hoặc cam kết từ xa cấu hình để biết bạn muốn tìm nạp thông tin gì. Sử dụng git fetch HEAD sẽ cho biết HEAD là điều khiển từ xa trong kho lưu trữ của bạn. Đó là lệnh làm việc mà không có lỗi là tò mò.

Ví dụ: Kết quả git fetch HEAD trong kho Tôi hiện đang làm việc trong các lỗi sau

fatal: 'HEAD' does not appear to be a git repository 
fatal: Could not read from remote repository. 

Please make sure you have the correct access rights 
and the repository exists. 

Lệnh git remote sẽ liệt kê tất cả các điều khiển từ xa, trong khi git remote --verbose sẽ bao gồm địa chỉ của điều khiển từ xa. Bạn có thể sử dụng điều này để xem bạn có điều khiển từ xa là HEAD và địa chỉ từ xa mà bạn bè của bạn lưu trữ không?

Tuy nhiên, câu hỏi của tôi đã qua một bên và giúp xóa bỏ sự nhầm lẫn của bạn. Lệnh git fetch ... chỉ cập nhật từ xa refs - chứ không phải từ cục bộ của bạn.

Để làm cho điều này rõ ràng, hãy nhìn vào bên trong thư mục .git trong kho lưu trữ của bạn (nó được ẩn theo mặc định để bạn có thể cần phải hiện nó).Bạn sẽ tìm thấy một cấu trúc thư mục tương tự như sau

working directory 
|=>.git 
| |=>objects   <= contains data for each commit 
| |=>refs 
|  |=>heads 
|  |-master  <= file containing current commit of local master branch 
|  |=>remotes 
|  |=>origin 
|   |-master <= file containing current commit of remote origin's master branch 
|-FETCH_HEAD   <= file updated by `git fetch`, contains info of what was fetched 

Giả sử bạn kiểm tra các chi nhánh chủ, git checkout master - git sẽ thay đổi thư mục làm việc của bạn để phù hợp với dữ liệu cam kết trong thư mục 'đối tượng' phù hợp với giá trị cam kết trong tệp '.git/refs/heads/master'.

Nếu bạn sau đó git fetch origin master, tệp '.git/refs/remotes/origin/master' được cập nhật thành cam kết của nhánh chính trên nguồn gốc từ xa - và tất cả dữ liệu cam kết cần thiết cho cam kết đó được tải xuống và đặt trong thư mục 'đối tượng'.

Điểm quan trọng ở đây là git fetch không cập nhật thư mục làm việc của bạn phản ánh chi nhánh địa phương được kiểm tra và git fetch không bao giờ cập nhật chi nhánh địa phương.

Sử dụng git merge ... hoặc git rebase ... là cần thiết để cập nhật chi nhánh master địa phương với các thay đổi trong origin/master. git pull ... thực hiện cả hai git fetch ...git merge ... hoặc git rebase ..., tùy thuộc vào tùy chọn và cấu hình (git merge ... là mặc định).

Sau tất cả giải thích đó, bạn muốn có thể xem điều gì - nếu có - được tìm nạp từ kho lưu trữ bạn bè của bạn. Lệnh git branch -avv sẽ liệt kê tất cả các nhánh địa phương và từ xa, với số cam kết và trong trường hợp của các nhánh địa phương, nhánh nào đang theo dõi từ xa.

Để xem cách các chi nhánh liên quan đến nhau, tôi thấy hữu ích khi sử dụng công cụ để vẽ biểu đồ cây kho. Có một số để lựa chọn nhưng tôi tìm thấy lệnh git log đủ; chẳng hạn như git log --all --graph --oneline --decorate. Cảnh báo công bằng, điều này có thể khá dài và phức tạp cho một kho lưu trữ lớn. Có thể thu được đầu ra ngắn hơn bằng cách thêm đối số --simplify-by-decoration.

Để tóm tắt: nếu bạn có thể khắc phục ở nhà tùy thuộc vào thông tin trong kho lưu trữ của bạn. Các lệnh được đề cập ở trên; git remote --verbose, git branch -avvgit log ... phải cung cấp cho bạn sự hiểu biết về trạng thái hiện tại của kho lưu trữ của bạn. Từ đó, bạn có thể xác định xem bạn có cần làm gì khác để lấy dữ liệu trong chi nhánh địa phương của mình bằng cách sử dụng git merge hoặc git rebase hay không.

Như mọi khi, nếu bạn gặp rắc rối, hãy đăng lại với những gì bạn tìm hiểu.

+0

Bạn nói đúng. Những gì tôi thực sự làm là git fetch origin HEAD. Tôi đã làm điều đó bởi vì tôi không biết liệu anh ấy có đang cập nhật nhánh chủ của mình không, nên tôi nghĩ rằng HEAD sẽ ám chỉ đến bất cứ nhánh nào anh ta đang làm việc. Tôi vẫn chưa theo dõi vấn đề, nhưng cảm ơn sự giúp đỡ. – DanielF

+1

upvote cho sự chú ý rực rỡ đến từng chi tiết. "Git pull ... làm cả git fetch ... và git merge ... hoặc git rebase ..., tùy thuộc vào tùy chọn và cấu hình (git merge ... là mặc định). " – hAcKnRoCk

3

git fetch không thực sự chạm vào thư mục làm việc của bạn. Nó chỉ tìm nạp những thay đổi mới nhất từ ​​điều khiển từ xa. Để cập nhật trạng thái hiện tại của bạn git merge hoặc git rebase. Ngoài ra, bạn có thể sử dụng git pull hoạt động như phím tắt tới git fetch + git merge.

Sự khác biệt chính giữa hợp nhất và rebase là trong một số trường hợp hợp nhất sẽ tạo một cam kết mới, với trạng thái tích lũy (không hợp nhất chuyển tiếp nhanh). IMHO này là xấu, như nhắc tôi về những lần tôi sử dụng SVN. Rebase chỉ replay các thay đổi của bạn trên đầu của cam kết quy định, vì vậy lịch sử của bạn luôn luôn là tuyến tính. Chỉ cần chắc chắn sử dụng cùng một luồng như đồng nghiệp của bạn.

Tôi khuyên bạn nên đọc một số nội dung về git nói chung và luồng git: a must-read booka good article.

1

Những gì bạn muốn làm là:

  • Thêm một từ xa cho đồng nghiệp
  • bạn Fetch những thay đổi từ kho lưu trữ của mình
  • Tạo một chi nhánh địa phương trong đó đề cập đến chi nhánh từ xa của ông

Có lẽ, bạn đã thực hiện bướC# 1. Nhưng đối đầy đủ, đó là:

git remote add coworker git://path/to/coworkers/repo.git

nơi URL có thể là bất kỳ định dạng URL mà git hỗ trợ.

Bây giờ bạn đã cho biết thêm từ xa, bạn muốn lấy những thay đổi của mình:

git fetch coworker

này cung cấp cho bạn các chi nhánh từ xa đối với từng chi nhánh của mình. Giả sử nhánh của anh ta được gọi là "hamster". Bây giờ, để làm việc, bạn tạo bản sao cục bộ của riêng bạn của chi nhánh từ xa

git checkout -b hamster coworker/hamster

Điều này tạo ra và chuyển bạn đến một chi nhánh gọi là chuột đồng.

Từ thời điểm đó trở đi, bạn có thể làm việc trên chuột và đẩy nó để anh ta với

git push coworker hamster

lần đầu tiên, và sau đó chỉ cần git push sau đó.

Bất cứ lúc nào bạn muốn kéo xuống và hợp nhất các thay đổi của mình, bạn có thể làm:

git pull

8

Kể từ git 1.8.4 (tháng 8 năm 2013), git fetch sẽ cập nhật các chi nhánh theo dõi từ xa! Không chỉ FETCH_HEAD.

Xem commit f269048 từ Jeff King (peff):

Khi chúng tôi chạy một thường xuyên "git fetch" không có đối số, chúng tôi cập nhật các refs theo dõi theo refspec cấu hình.
Tuy nhiên, khi chúng tôi chạy "git fetch origin master" (hoặc "git pull origin master"), chúng tôi không xem xét các thông số tinh chỉnh được định cấu hình và chỉ cập nhật FETCH_HEAD.

Chúng tôi bỏ lỡ cơ hội cập nhật "refs/remotes/origin/master" (hoặc bất kỳ điều gì người dùng đã định cấu hình). Một số người dùng tìm thấy điều này gây nhầm lẫn, bởi vì họ muốn làm so sánh hơn nữa chống lại trạng thái cũ của thuyền trưởng từ xa, như:

$ git pull origin master 
$ git log HEAD...origin/master 
+1

Git 1.9/2.0 (Q1 2014): 'git push' có hành vi đối xứng: https://github.com/git/git/commit/ca02465b41311fe7634acb9bb5b5c61975ef5f38 – VonC

Các vấn đề liên quan