Tại sao trạng thái git hiển thị chi nhánh được cập nhật khi thay đổi tồn tại ngược dòng?


226

Các thay đổi tồn tại ngược dòng trong một nhánh được theo dõi, nhưng khi tôi gõ, git statusnó chỉ ra rằng nhánh cục bộ của tôi được cập nhật. Đây có phải là hành vi mới, tôi đã thay đổi cài đặt cấu hình hay có gì sai?

Cảm ơn đã giúp đỡ.

ubuntu@host:/my/repo# git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean


ubuntu@host:/my/repo# git pull
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 11 (delta 6), reused 0 (delta 0)
Unpacking objects: 100% (11/11), done.
From bitbucket.org:my/repo
   1234567..abcdefg  master     -> origin/master
Updating 1234567..abcdefg
Fast-forward
 file1        |  1 -
 file2        | 43 +++++++++++++++++++++++++++++++++++++++++++
 file3        | 21 ++++++++++++---------
 file4        | 21 ++++++++++++---------
 4 files changed, 67 insertions(+), 19 deletions(-)
 create mode 100644 file5

Câu trả lời:


274

Điều mà trạng thái đang nói với bạn là bạn đứng sau giới thiệu được gọi origin/master là ref địa phương trong repo địa phương của bạn . Trong trường hợp này, ref xảy ra để theo dõi một nhánh trong một số điều khiển từ xa, được gọi origin, nhưng trạng thái không cho bạn biết bất cứ điều gì về nhánh trên điều khiển từ xa. Nó cho bạn biết về ref, đó chỉ là một ID cam kết được lưu trữ trên hệ thống tệp cục bộ của bạn (trong trường hợp này, nó thường nằm trong một tệp được gọi .git/refs/remotes/origin/mastertrong repo cục bộ của bạn).

git pullthực hiện hai hoạt động; đầu tiên, nó thực hiện git fetchđể cập nhật các cam kết trong repo từ xa (cập nhật origin/masterref trong repo cục bộ của bạn), sau đó nó thực hiện git mergeđể hợp nhất các cam kết đó vào nhánh hiện tại.

Cho đến khi bạn thực hiện fetchbước (một mình hoặc thông qua git pull) thì repo cục bộ của bạn không có cách nào để biết rằng có thêm các cam kết ngược dòng và git statuschỉ nhìn vào origin/masterref địa phương của bạn .

Khi git statusnói cập nhật, nó có nghĩa là "cập nhật với chi nhánh mà chi nhánh hiện tại theo dõi", trong trường hợp này có nghĩa là "cập nhật với giới thiệu địa phương được gọi origin/master". Điều đó chỉ tương đương với "cập nhật với trạng thái ngược dòng đã được truy xuất lần trước khi chúng tôi thực hiện fetch" không giống như "cập nhật với trạng thái trực tiếp mới nhất của thượng nguồn".

Tại sao nó hoạt động theo cách này? Vâng fetchbước là một mạng lưới hoạt động có khả năng chậm và tốn kém. Thiết kế của Git (và các hệ thống kiểm soát phiên bản phân tán khác ) là để tránh các hoạt động mạng khi không cần thiết và là một mô hình hoàn toàn khác với hệ thống máy khách-máy chủ thông thường mà nhiều người đã sử dụng (mặc dù như đã nêu trong các nhận xét bên dưới, khái niệm của Git của một "nhánh theo dõi từ xa" gây nhầm lẫn ở đây không được chia sẻ bởi tất cả các DVCS). Hoàn toàn có thể sử dụng Git ngoại tuyến, không có kết nối với máy chủ tập trung và đầu ra git statusphản ánh điều này.

Tạo và chuyển đổi các nhánh (và kiểm tra trạng thái của chúng) trong Git được coi là nhẹ, không phải là thứ thực hiện một hoạt động mạng chậm đến một hệ thống tập trung. Giả định khi thiết kế Git và git statusđầu ra là người dùng hiểu điều này (quá nhiều tính năng Git chỉ có ý nghĩa nếu bạn đã biết cách Git hoạt động). Với việc áp dụng Git bởi rất nhiều người dùng không quen thuộc với DVCS, giả định này không phải lúc nào cũng hợp lệ.


79
Một bình luận muộn nhưng tôi đã rơi vào tình huống tương tự. Tôi hiểu tại sao git không có cách nào để biết về những thay đổi trước khi tìm nạp. Nhưng sau đó không nên nói "cập nhật" mà đơn giản là không đúng. Tốt hơn nên nói "không biết điều gì có thể xảy ra từ xa".
Droidum

31
Có lẽ nó hoàn toàn hợp lý, nhưng nó hoàn toàn không hợp lý. Tại sao bạn không thiết kế nó để tìm nạp và THEN tuyên bố liệu nó có được cập nhật không? Hoặc thay đổi thông báo để cho biết những gì nó thực sự đã làm, ví dụ: "Chi nhánh của bạn đã được cập nhật với 'origin / master' khi được kiểm tra lần cuối tại {timestamp}"? Hoặc thậm chí chỉ cần nói, "Hãy tìm nạp để tìm hiểu xem chi nhánh của bạn có được cập nhật không"?
Colin ngày

25
Tại sao phải hiển thị thông báo "Chi nhánh của bạn được cập nhật" cả? Tôi không thấy một điểm nào trong việc biết trạng thái của nguồn gốc / bản gốc và nếu nó được cho là đại diện cho nhánh chính thực sự trên điều khiển gốc, thì rõ ràng nó không có ý tưởng nào.
whiterook6

2
@pastullo, vì vậy hãy tạo một bí danh.
Jonathan Wakely

23
Đây là một ví dụ hoàn hảo về khả năng sử dụng khủng khiếp của Git. Tôi yêu sức mạnh và tính linh hoạt của nó nhưng chỉ đơn giản là thay đổi thông điệp thành một cái gì đó như "Chi nhánh của bạn được cập nhật với phiên bản địa phương của 'origin / master'." sẽ là một cải tiến rất lớn Sự nhầm lẫn ở đây là nguồn gốc / chủ nhánh cục bộ (mẫu khớp với bất kỳ điều khiển từ xa / nhánh nào bạn đang sử dụng) theo dõi một nhánh từ xa.
matthewcummings516

35

Điều này là do repo cục bộ của bạn chưa được đăng ký với điều khiển từ xa ngược dòng. Để có tác phẩm này như bạn mong đợi, hãy sử dụng git fetchrồi chạy git statuslại.


7

Mặc dù đây đều là những câu trả lời khả thi, tôi quyết định đưa ra cách kiểm tra xem repo cục bộ có phù hợp với điều khiển từ xa hay không, tìm nạp hoặc kéo. Để xem các chi nhánh của tôi ở đâu, tôi chỉ cần sử dụng:

git remote show origin

Những gì nó làm là trả về tất cả các nhánh được theo dõi hiện tại và quan trọng nhất - thông tin cho dù chúng được cập nhật, trước hoặc sau các nhánh gốc từ xa. Sau lệnh trên, đây là một ví dụ về những gì được trả về:

  * remote origin
  Fetch URL: https://github.com/xxxx/xxxx.git
  Push  URL: https://github.com/xxxx/xxxx.git
  HEAD branch: master
  Remote branches:
    master      tracked
    no-payments tracked
  Local branches configured for 'git pull':
    master      merges with remote master
    no-payments merges with remote no-payments
  Local refs configured for 'git push':
    master      pushes to master      (local out of date)
    no-payments pushes to no-payments (local out of date)

Hy vọng điều này sẽ giúp được ai đó.


0

"origin / master" dùng để chỉ tham chiếu sẵn sàng cho cam kết CHÍNH của nhánh "origin / master". Tham chiếu là tên bí danh thân thiện với con người đối với đối tượng Git, thường là đối tượng cam kết. Tham chiếu "nguồn gốc / chủ" chỉ được cập nhật khi bạn git pushtruy cập từ xa ( http://git-scm.com/book/en/v2/Git-Iternals-Git-References#Remotes ).

Từ trong thư mục gốc của dự án, hãy chạy:

cat .git/refs/remotes/origin/master

So sánh ID cam kết được hiển thị với:

cat .git/refs/heads/master

Chúng phải giống nhau, và đó là lý do tại sao Git nói masterlà cập nhật origin/master.

Khi bạn chạy

git fetch origin master

Điều đó lấy ra các đối tượng Git mới cục bộ trong thư mục .git / object. Và Git cập nhật .git / FETCH_HEAD để bây giờ, nó trỏ đến cam kết mới nhất của nhánh được tìm nạp.

Vì vậy, để xem sự khác biệt giữa chi nhánh địa phương hiện tại của bạn và chi nhánh được tìm nạp từ thượng nguồn, bạn có thể chạy

git diff HEAD FETCH_HEAD

1
Bạn không nên chọn các mục trong thư mục .git, nó sẽ không hoạt động với các ref được đóng gói. Ngoài ra, hành vi tìm nạp mà bạn mô tả là dành cho các phiên bản cũ hơn của git.
Andrew C

Không phải origin/masterref cũng được cập nhật bằng cách tìm nạp, cũng như đẩy?
Jonathan Wakely 7/1/2015

Chính xác. Tôi đã sử dụng Git 1.8.3 cho đến nay. Tôi thực sự có thể nhận thấy với phiên bản 2.2.1, FETCH_HEAD cũng được cập nhật trong quá trình tìm nạp. Ngoài ra, khi có thông báo "Chi nhánh của bạn được cập nhật với ..." hoặc "Chi nhánh của bạn đứng sau ... bởi X cam kết", nó chỉ hiển thị nếu chi nhánh địa phương của bạn theo dõi một chi nhánh từ xa nhất định. Để master theo dõi nguồn gốc / master, người ta phải chạy git Branch -u origin / master từ nhánh master. Nếu không có theo dõi, bạn vẫn cần chạy git diff.
Marek Stanley

Vậy thì tôi khuyên bạn nên sửa câu nói rằng "tham chiếu gốc / chủ" chỉ được cập nhật khi bạn git đẩy vào điều khiển từ xa '
Jonathan Wakely

0

Hãy xem xét một repo mẫu git để xác minh nếu your branch (master)up to datevới origin/master.

Xác minh rằng chủ địa phương đang theo dõi nguồn gốc / chủ:

$ git branch -vv
* master a357df1eb [origin/master] This is a commit message

Thông tin thêm về chi nhánh chính địa phương:

$ git show --summary
commit a357df1eb941beb5cac3601153f063dae7faf5a8 (HEAD -> master, tag: 2.8.0, origin/master, origin/HEAD)
Author: ...
Date:   Tue Dec 11 14:25:52 2018 +0100

    Another commit message

Xác minh nếu nguồn gốc / chủ nằm trên cùng một cam kết:

$ cat .git/packed-refs | grep origin/master
a357df1eb941beb5cac3601153f063dae7faf5a8 refs/remotes/origin/master

Chúng ta có thể thấy cùng một hàm băm xung quanh và an toàn để nói rằng nhánh này phù hợp với điều khiển từ xa, ít nhất là trong repo git hiện tại.



0

Câu trả lời tầm thường nhưng chính xác trong một số trường hợp, chẳng hạn như câu trả lời đã đưa tôi đến đây. Tôi đã làm việc trong một repo mới đối với tôi và tôi đã thêm một tệp không được xem là mới bởi trạng thái.

Nó kết thúc rằng tệp khớp với một mẫu trong tệp .gitignore.


0

trong trường hợp này, sử dụng git add và tích hợp tất cả các tệp đang chờ xử lý và sau đó sử dụng git commit và sau đó git đẩy

git add - tích hợp tất cả các tập tin pedent

cam kết git - lưu cam kết

git đẩy - lưu vào kho

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.