'git pull origin mybranch' để lại local mybranch N cam kết trước origin. Tại sao?


92

Tôi vừa quan sát thấy điều gì đó kỳ lạ git pull, mà tôi không hiểu.

Vào thứ sáu, tôi làm việc tại một chi nhánh địa phương. chúng ta hãy gọi nó mybranch. Trước khi rời khỏi văn phòng tôi đẩy nó đến nguồn gốc (đó là github repo của tôi): git push origin mybranch.

Hôm qua ở nhà, tôi chỉnh sửa pullmybranch vào máy tính xách tay của mình, thực hiện thêm một số mã hóa và sau đó đẩy các thay đổi của tôi trở lại github (origin).

Bây giờ tôi đang làm việc trở lại và cố gắng kéo các thay đổi từ hôm qua vào máy làm việc của mình (tôi đã không thay đổi bất kỳ điều gì trong repo cục bộ của nơi làm việc vào cuối tuần):

git pull origin mybranch

điều đó gây ra hợp nhất tua đi nhanh, điều này tốt. Sau đó tôi đã làm một git status, và nó nói:

# On branch mybranch
# Your branch is ahead of 'origin/mybranch' by 6 commits.
#
nothing to commit (working directory clean)

Huh? Làm thế nào nó có thể vượt lên trước 6 cam kết khi tôi thậm chí còn không chạm vào nó vào cuối tuần, VÀ chỉ lấy từ nguồn gốc? Vì vậy, tôi đã chạy một git diff origin/mybranchvà sự khác biệt chính xác là 6 thay đổi tôi vừa kéo từ điều khiển từ xa.

Tôi chỉ có thể "sửa chữa" điều này bằng cách chạy git fetch origin:

From git@github.com:me/project
af8be00..88b0738  mybranch -> origin/mybranch

Rõ ràng, repo cục bộ của tôi đã thiếu một số đối tượng tham chiếu, nhưng làm thế nào có thể được? Ý tôi là, một pull hiện đã tìm nạp và tôi đã không làm việc trên bất cứ thứ gì ngoại trừ nhánh đó, vì vậy a git fetch origingit fetch origin mybranchphải có cùng kết quả?

Tôi có nên luôn sử dụng git pull originthay vì git pull origin branchname?

Tôi bối rối.


Tôi cũng nhận thấy điều này; một git pushý chí dường như cũng giải quyết được nó (báo cáo "tất cả được cập nhật").
Ben James

4
git config --get-regexp br.*có thể cho bạn biết nếu cấu hình của bạn có một chi nhánh cục bộ đang theo dõi một chi nhánh khác
VonC

3
Bạn có thể nhập git config branch.master.remote yourGitHubRepo.gitworkRepo của mình và kiểm tra (ở phần tiếp theo git pull origin) nếu trạng thái vẫn có cảnh báo 'phía trước' không?
VonC

nó không được đặt (đầu ra trống). nhưng git remote show originhiển thị cho tôi rằng nguồn gốc trỏ đến kho lưu trữ GitHub của tôi, vì vậy điều đó có ổn không?
Matthias

1
chỉ git remote (hiển thị địa chỉ phù hợp cho repo GitHub) là không đủ . Để tránh phải "một Your branch is ahead" thông điệp cảnh báo sau một git pull, bạn cần đầu tiên cũng xác định tên từ xa cho một chi nhánh . Do đó, gợi ý của tôi: nhập git config branch.master.remote yourGitHubRepo.git, sau đó thử a git pullvà a git statusvà xem vấn đề vẫn còn.
VonC

Câu trả lời:


115

git pullcác lệnh gọi git fetchvới các tham số thích hợp trước khi hợp nhất các đầu được tìm nạp rõ ràng (hoặc nếu không có nhánh nào được định cấu hình từ xa để hợp nhất) vào nhánh hiện tại.

Cú pháp: git fetch <repository> <ref>trong đó <ref>chỉ là một tên nhánh không có dấu hai chấm là tìm nạp 'một lần' không thực hiện tìm nạp tiêu chuẩn của tất cả các nhánh được theo dõi của điều khiển từ xa được chỉ định mà thay vào đó chỉ tìm nạp nhánh được đặt tên vào FETCH_HEAD.

Cập nhật: đối với các phiên bản Git kể từ 1.8.4, nếu có nhánh theo dõi từ xa theo dõi ref mà bạn đã yêu cầu tìm nạp thì nhánh theo dõi sẽ được cập nhật fetch. Thay đổi này đã được thực hiện cụ thể để tránh nhầm lẫn mà hành vi trước đó gây ra.

Khi bạn thực hiện git pull <repository> <ref>, FETCH_HEADđược cập nhật như trên, sau đó được hợp nhất vào mục đã kiểm tra của bạn HEADnhưng không có nhánh theo dõi tiêu chuẩn nào cho kho lưu trữ từ xa sẽ được cập nhật (Git <1.8.4). Điều này có nghĩa là cục bộ có vẻ như bạn đang đi trước chi nhánh từ xa, trong khi trên thực tế, bạn đã cập nhật nó.

Cá nhân tôi luôn làm git fetchtheo git merge <remote>/<branch>vì tôi nhận được bất kỳ cảnh báo nào về cập nhật bắt buộc trước khi hợp nhất và tôi có thể xem trước những gì tôi đang hợp nhất. Nếu tôi sử dụng git pullnhiều hơn một chút, tôi sẽ thực hiện đơn giản git pullmà không có tham số nào. của thời gian, dựa vào branch.<branch>.remotebranch.<branch>.mergeđể 'làm điều đúng đắn'.


4
+1 Đó thực sự là một lời giải thích hay! Tôi biết những lời giải thích đã được ẩn ở đâu đó bên trong 'giúp đỡ git fetch' nhưng không thể có được nó ra ...
Stefan Näwe

1
+1. Bài tốt, với một cách tiếp cận tương tự như gitster.livejournal.com/28309.html
VonC

1
Vì vậy, liệu git fetchsau khi git pull <repository> <ref>khắc phục sự cố vì tìm nạp sẽ cập nhật các nhánh theo dõi tiêu chuẩn? Ngoài ra, cảm ơn vì câu trả lời này, bắt đầu có ý nghĩa :)
Bart Jedrocha

1
Tôi cũng gặp phải vấn đề này và bạn sẽ cần phải làm gì git fetchtiếp theo git merge origin/master master.
user1027169

3

Điều gì sẽ git remote -v showtrả lại khi nói đến nguồn gốc?

Nếu nguồn gốc trỏ đến github, trạng thái phải được cập nhật và không đi trước bất kỳ repo từ xa nào. Ít nhất, với Git1.6.5 mà tôi đang sử dụng để kiểm tra nhanh.

Dù sao, để tránh điều này, hãy xác định rõ ràng repo từ xa của nhánh chính:

$ git config branch.master.remote yourGitHubRepo.git

thì a git pull origin master, theo sau là a git statussẽ trả về trạng thái sạch (không có phía trước).
Tại sao? bởi vì master gốc get fetch (được bao gồm trong git pull origin master) sẽ không chỉ cập nhật FETCH_HEAD(như Charles Bailey giải thích trong câu trả lời của mình ) mà còn cập nhật "nhánh chính từ xa" trong kho lưu trữ Git cục bộ của bạn.
Trong trường hợp đó, máy chủ cục bộ của bạn dường như sẽ không còn "đi trước" máy chủ từ xa nữa.


Tôi có thể kiểm tra điều này, với git1.6.5:

Đầu tiên, tôi tạo một workrepo:

PS D:\git\tests> cd pullahead
PS D:\git\tests\pullahead> git init workrepo
Initialized empty Git repository in D:/git/tests/pullahead/workrepo/.git/
PS D:\git\tests\pullahead> cd workrepo
PS D:\git\tests\pullahead\workrepo> echo firstContent > afile.txt
PS D:\git\tests\pullahead\workrepo> git add -A 
PS D:\git\tests\pullahead\workrepo> git commit -m "first commit"

Tôi mô phỏng một repo GitHub bằng cách tạo một repo trần (một repo có thể nhận được đẩy từ mọi nơi)

PS D:\git\tests\pullahead\workrepo> cd ..
PS D:\git\tests\pullahead> git clone --bare workrepo github

Tôi thêm một modif vào repo đang làm việc của mình, mà tôi đẩy sang repo github (được thêm vào dưới dạng điều khiển từ xa)

PS D:\git\tests\pullahead> cd workrepo
PS D:\git\tests\pullahead\workrepo> echo aModif >> afile.txt
PS D:\git\tests\pullahead\workrepo> git ci -a -m "a modif to send to github"
PS D:\git\tests\pullahead\workrepo> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo> git push github

Tôi tạo một kho lưu trữ gia đình, sao chép của GitHub, trong đó tôi thực hiện một số sửa đổi, được đẩy lên GitHub:

PS D:\git\tests\pullahead\workrepo> cd ..
PS D:\git\tests\pullahead> git clone github homerepo
PS D:\git\tests\pullahead> cd homerepo
PS D:\git\tests\pullahead\homerepo> type afile.txt
firstContent
aModif

PS D:\git\tests\pullahead\homerepo> echo aHomeModif1  >> afile.txt
PS D:\git\tests\pullahead\homerepo> git ci -a -m "a first home modif"
PS D:\git\tests\pullahead\homerepo> echo aHomeModif2  >> afile.txt
PS D:\git\tests\pullahead\homerepo> git ci -a -m "a second home modif"
PS D:\git\tests\pullahead\homerepo> git push github

Sau đó tôi sao chép workrepo cho thử nghiệm đầu tiên

PS D:\git\tests\pullahead\workrepo4> cd ..
PS D:\git\tests\pullahead> git clone workrepo workrepo2
Initialized empty Git repository in D:/git/tests/pullahead/workrepo2/.git/
PS D:\git\tests\pullahead> cd workrepo2
PS D:\git\tests\pullahead\workrepo2> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo2> git pull github master
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From d:/git/tests/pullahead/github
 * branch            master     -> FETCH_HEAD
Updating c2763f2..75ad279
Fast forward
 afile.txt |  Bin 46 -> 98 bytes
 1 files changed, 0 insertions(+), 0 deletions(-)

Trong repo đó, trạng thái git có đề cập đến địa lý chính trước ' origin':

PS D:\git\tests\pullahead\workrepo5> git status
# On branch master
# Your branch is ahead of 'origin/master' by 2 commits.
#
nothing to commit (working directory clean)

Nhưng đó originkhông phải là github:

PS D:\git\tests\pullahead\workrepo2> git remote -v show
github  d:/git/tests/pullahead/github (fetch)
github  d:/git/tests/pullahead/github (push)
origin  D:/git/tests/pullahead/workrepo (fetch)
origin  D:/git/tests/pullahead/workrepo (push)

Nhưng nếu tôi lặp lại trình tự trong repo có nguồn gốc là github (hoặc không có nguồn gốc nào cả, chỉ là 'github' từ xa được xác định), trạng thái là sạch:

PS D:\git\tests\pullahead\workrepo2> cd ..
PS D:\git\tests\pullahead> git clone workrepo workrepo4
PS D:\git\tests\pullahead> cd workrepo4
PS D:\git\tests\pullahead\workrepo4> git remote rm origin
PS D:\git\tests\pullahead\workrepo4> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo4> git pull github master
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From d:/git/tests/pullahead/github
 * branch            master     -> FETCH_HEAD
Updating c2763f2..75ad279
Fast forward
 afile.txt |  Bin 46 -> 98 bytes
 1 files changed, 0 insertions(+), 0 deletions(-)
PS D:\git\tests\pullahead\workrepo4> git status
# On branch master
nothing to commit (working directory clean)

Nếu tôi chỉ origintrỏ vào github, statusgit1.6.5 sẽ sạch.
Nó có thể có một cảnh báo 'phía trước' cho git trước đó, nhưng dù sao, một git config branch.master.remote yourGitHubRepo.gitđịnh nghĩa rõ ràng sẽ có thể xử lý điều đó, ngay cả với các phiên bản đầu tiên của Git.


Cảm ơn vì đã dành thời gian xem xét vấn đề này. Điều khiển từ xa gốc đã trỏ đến repo GitHub của tôi. Tôi đã sao chép dự án đó từ url GitHub và chi nhánh chính cục bộ của tôi đang theo dõi nguồn gốc / chính. Đối với mybranch, tôi khá chắc chắn rằng tôi đã tạo nó từ nhánh origin / mybranch, nhánh này sẽ tự động theo dõi nó. Nhưng vẫn có thể đây là vấn đề? Rằng mybranch cục bộ không thực sự theo dõi nguồn gốc / mybranch? Tái bút: Tôi đang sử dụng git 1.6.1 (thông qua MacPorts).
Matthias

Có lệnh git để tôi xem liệu một nhánh cục bộ có đang theo dõi một nhánh khác không? Tôi không thể tìm thấy nó trong các trang đàn ông.
Matthias

Bạn có thể xem các chi nhánh từ xa được theo dõi git remote show origin.
Ted Percival

2

Bạn có cẩn thận thêm tất cả điều khiển từ xa của mình (ngoại trừ originđiều khiển đi kèm với bản sao gốc của bạn) bằng cách sử dụng git remote add NAME URLkhông? Tôi đã thấy lỗi này khi chúng vừa được thêm vào cấu hình git.


Tôi đã làm điều này khi nhân bản repo. Tuy nhiên, tôi đã không làm điều này với từng nhánh. Ví dụ: mybranch, trước tiên tôi sẽ tìm nạp từ nguồn gốc, sau đó git checkout -b mybranch origin/mybranch. Theo trang man của git-branch, origin / mybranch là điểm bắt đầu, và hơn nữa, nó tuyên bố cho --track: "... Sử dụng điều này nếu bạn luôn kéo từ cùng một nhánh ngược dòng vào nhánh mới và nếu bạn không muốn sử dụng rõ ràng "git pull <repository> <refspec>". Hành vi này là mặc định khi điểm bắt đầu là một nhánh từ xa. "
Matthias
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.