Phân nhánh Git: master so với origin / master so với điều khiển từ xa / origin / master


201

Tôi nghĩ rằng tôi đang đi đúng hướng để hiểu các khái niệm cơ bản của git.

Tôi đã thiết lập và nhân bản một kho lưu trữ từ xa. Tôi cũng đã tạo một kho lưu trữ trống phía máy chủ và liên kết kho lưu trữ cục bộ của tôi với nó.

Vấn đề của tôi là tôi không hiểu sự khác biệt giữa:

  • nguồn gốc / chủ so với điều khiển từ xa / nguồn gốc / chủ

Theo như tôi đã hiểu, master là một nhánh địa phương và điều khiển từ xa / origin / master là một điều khiển từ xa.

Nhưng chính xác nguồn gốc / chủ là gì?


1
@ChristopherWallace: Bạn đã gây ra hai câu hỏi về meta với chỉnh sửa của mình: " Chúng ta có thực sự cần thẻ [origin] không? " Và " Master [thật] là gì? ".
Ded repeatator

@Ded repeatator Có phải là một vấn đề?
nbro

@ChristopherWallace: Chà, nhiều người dường như nghĩ cả hai thẻ (thẻ bạn đã tạo và thẻ bạn vừa thêm) đều xấu. Tôi tình cờ đồng tình, nhưng có lẽ bạn có điều gì đó để thêm vào cuộc thảo luận được liên kết không được xem xét. Nếu không, có vẻ như vậy.
Ded repeatator


Theo dõi câu hỏi: Tại sao .git/refs/origin/masterbao giờ trôi dạt từ .git/refs/remotes/origin/master? Điều này đang xảy ra với tôi bây giờ và tôi đang bị ném đi.
Paul

Câu trả lời:


219

Lấy một bản sao của một kho lưu trữ từ xa và chạy git branch -a(để hiển thị tất cả các nhánh mà git biết về). Nó có thể sẽ trông giống như thế này:

* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master

Ở đây, masterlà một nhánh trong kho lưu trữ cục bộ. remotes/origin/masterlà một nhánh có tên mastertrên remote có tên origin. Bạn có thể tham khảo điều này như một trong hai origin/master, như trong:

git diff origin/master..master

Bạn cũng có thể gọi nó là remotes/origin/master:

git diff remotes/origin/master..master

Đây chỉ là hai cách khác nhau để đề cập đến cùng một điều (tình cờ, cả hai lệnh này đều có nghĩa là "cho tôi thấy những thay đổi giữa masternhánh từ xa và masternhánh của tôi ).

remotes/origin/HEADdefault branchtừ xa được đặt tên origin. Điều này cho phép bạn chỉ cần nói originthay vì origin/master.


5
Câu trả lời tốt. Tôi nghĩ rằng git branch -ahiển thị nhánh từ xa remotes/origin/masterlà một phần vì ref được lưu trữ bên trong .git/refs/remotes/origin(nếu nó chưa được đóng gói). Theo tôi, đầu ra của git branch -acó thể rõ ràng hơn nhiều, có lẽ bằng cách tách tên của điều khiển từ xa với tên của nhánh với một cái gì đó không phải là dấu gạch chéo.
Matt Hurne

14
Cũng lưu ý rằng git branch -r, chỉ hiển thị các nhánh từ xa, sẽ hiển thị nhánh đó chỉ origin/masterremotes/tiền tố không cần thiết.
Matt Hurne

3
@misterb quyên: đúng vậy. Đầu ra khó hiểu hơn là làm rõ. Cảm ơn rất nhiều, một câu trả lời tuyệt vời cho câu hỏi của tôi đã cho tôi gợi ý đúng
John Rumpel

Nếu tôi nhìn vào git logtôi thấy commit fa9sd8jasdf98 (HEAD -> master), điều này có nghĩa là gì? Trong trường hợp này là gì? Tôi nghĩ rằng tôi hiện đang là "bậc thầy" và đang cam kết origin/master. Tôi nghĩ rằng tôi đã có một cái gì đó trộn lẫn, ai đó có thể giúp đỡ bình tĩnh? CẬP NHẬT EDIT: Tôi nghĩ rằng tôi đã nhận nó, có đúng không khi cho rằng CHÍNH hiện đang chỉ vào nhánh chính, có nghĩa là tôi hiện đang trong quá trình cam kết làm chủ?
Sebastian Nielsen

@SebastianNielsen có bạn đúng, phần CHÍNH -> phần chính có nghĩa là bạn hiện đang ở chi nhánh chính.
iRestMyCaseYourHonor

108

Câu trả lời ngắn gọn cho những người giả như tôi (bị đánh cắp từ Torek):

  • nguồn gốc / chủ là "nơi chủ đã ở đó lần trước tôi đã kiểm tra"
  • Master là "nơi chủ nhân ở đây dựa trên những gì tôi đã và đang làm"

9
nguồn gốc / master = sao lưu của máy từ xa, được cập nhật lần cuối cùng bạn kiểm tra tổng thể = bản sao của nguồn gốc / master
sakurashinken

40

Về mặt kỹ thuật không có thực sự bất kỳ "từ xa" những thứ ở tất cả 1 trong repo Git của bạn, có tên chỉ địa phương mà nên tương ứng với tên trên khác, repo khác nhau. Những cái tên được đặt origin/whateverban đầu sẽ khớp với những cái trên repo mà bạn đã nhân bản:

git clone ssh://some.where.out.there/some/path/to/repo # or git://some.where...

làm một bản sao địa phương của các repo khác. Trên đường đi, nó ghi chú tất cả các nhánh đã ở đó, và các cam kết đó được giới thiệu và gắn chúng vào repo địa phương của bạn dưới tên refs/remotes/origin/.

Tùy thuộc vào khoảng thời gian bạn đi trước bạn git fetchhoặc tương đương để cập nhật "bản sao của tôi về những gì đó.where.out.there", họ có thể thay đổi các chi nhánh của mình xung quanh, tạo những cái mới và xóa một số. Khi bạn thực hiện git fetch(hoặc git pullthực sự tìm nạp cộng với hợp nhất), repo của bạn sẽ tạo các bản sao của tác phẩm mới của họ và thay đổi tất cả các refs/remotes/origin/<name>mục khi cần. Đó là khoảnh khắc fetching khiến mọi thứ khớp với nhau (ừm, và bản sao ban đầu, và một số trường hợp pushing quá cơ bản bất cứ khi nào Git có cơ hội kiểm tra, nhưng hãy xem cảnh báo bên dưới).

Git thường có bạn tham khảo của riêng bạn refs/heads/<name>như chỉ <name>, và những người ở xa như origin/<name>, và tất cả chỉ hoạt động vì nó rõ ràng đó là một trong đó. Đôi khi có thể tạo tên chi nhánh của riêng bạn khiến nó không rõ ràng, nhưng đừng lo lắng về điều đó cho đến khi nó xảy ra. :-) Chỉ cần đặt cho Git cái tên ngắn nhất làm cho nó rõ ràng và nó sẽ xuất phát từ đó: origin/masterlà "nơi chủ nhân đã ở đó lần trước tôi đã kiểm tra" và masterlà "nơi chủ nhân ở đây dựa trên những gì tôi đã làm" . Chạy git fetchđể cập nhật Git trên "nơi chủ ở đó" khi cần thiết.


Hãy cẩn thận: trong các phiên bản Git cũ hơn 1.8.4, git fetchcó một số chế độ không cập nhật "nơi chủ ở đó" (chính xác hơn là các chế độ không cập nhật bất kỳ nhánh theo dõi từ xa nào). Chạy git fetch origin, hoặc git fetch --all, hoặc thậm chí chỉ git fetch, không cập nhật. Chạy git fetch origin master không . Thật không may, chế độ "không cập nhật" này được kích hoạt bởi thông thường git pull. (Điều này chủ yếu chỉ là một phiền toái nhỏ và được khắc phục trong Git 1.8.4 trở lên.)


1 Vâng, có một thứ được gọi là "điều khiển từ xa". Nhưng đó cũng là địa phương! Tên originlà thứ Git gọi là "một điều khiển từ xa". Về cơ bản, đây chỉ là một tên ngắn gọn cho URL bạn đã sử dụng khi bạn sao chép. Đây cũng là nơi các origintrong origin/masterđến từ đâu. Tên origin/masternày được gọi là một nhánh theo dõi từ xa , đôi khi được rút ngắn thành "nhánh từ xa", đặc biệt là trong các tài liệu cũ hơn hoặc không chính thức.


2
Mô tả tuyệt vời cho một người mới như tôi, cảm ơn bạn! Làm rõ lý do tại sao cô ấy origin/masterdán nhãn dán vào localbiểu đồ của repo chứ không phải trên biểu đồ remote(Tôi hết lòng giới thiệu bài thuyết trình "Git Happens" của Jessica Kerr cho những người mới biết git: vimeo.com/46010208 . Tôi đã gãi đầu trong khoảng thời gian từ 30:00 - 30: 19.)
người cao tuổi

11

Tôi sẽ cố gắng làm cho câu trả lời của @ ErichBSchulz đơn giản hơn cho người mới bắt đầu:

  • origin / master là trạng thái của nhánh master trên kho lưu trữ từ xa
  • master là trạng thái của nhánh master trên kho lưu trữ cục bộ

1
cố gắng tốt nhưng IMHO không last time I've checkedcó điểm quan trọng
Alexei Martianov

6
  1. nguồn gốc - Đây là một tên tùy chỉnh và phổ biến nhất để trỏ đến điều khiển từ xa.

$ git remote add origin https://github.com/git/git.git--- Bạn sẽ chạy lệnh này để liên kết dự án github của bạn với nguồn gốc. Ở đây nguồn gốc là do người dùng định nghĩa. Bạn có thể đổi tên nó bằng cách$ git remote rename old-name new-name


  1. master - Tên nhánh mặc định trong Git là master. Đối với cả máy tính từ xa và cục bộ.

  1. origin / master - Đây chỉ là một con trỏ để tham chiếu nhánh master trong repo từ xa. Hãy nhớ tôi nói điểm gốc đến từ xa.

$ git fetch origin- Tải các đối tượng và refs từ kho lưu trữ từ xa vào máy tính cục bộ của bạn [origin / master]. Điều đó có nghĩa là nó sẽ không ảnh hưởng đến nhánh chính cục bộ của bạn trừ khi bạn hợp nhất chúng bằng cách sử dụng$ git merge origin/master . Hãy nhớ kiểm tra nhánh chính xác nơi bạn cần hợp nhất trước khi chạy lệnh này

Lưu ý: Nội dung tìm nạp được biểu diễn dưới dạng một nhánh từ xa. Fetch cung cấp cho bạn cơ hội để xem xét các thay đổi trước khi tích hợp chúng vào bản sao dự án của bạn. Để hiển thị các thay đổi giữa bạn và từ xa$git diff master..origin/master


5

Một điều rõ ràng (và một điểm khiến tôi bối rối):

"điều khiển từ xa / nguồn gốc / ĐẦU là nhánh mặc định" không thực sự chính xác.

điều khiển từ xa / origin / master là nhánh mặc định trong kho lưu trữ từ xa (lần cuối bạn kiểm tra). ĐẦU không phải là một nhánh, nó chỉ trỏ đến một nhánh.

Hãy nghĩ về CHÍNH là khu vực làm việc của bạn. Khi bạn nghĩ về nó theo cách này thì 'git checkout Branchname' có ý nghĩa đối với việc thay đổi các tệp trong vùng làm việc của bạn thành của một nhánh cụ thể. Bạn "kiểm tra" các tập tin chi nhánh vào khu vực làm việc của bạn. ĐẦU cho tất cả các mục đích thực tế là những gì bạn có thể nhìn thấy trong khu vực làm việc của bạn.


Chính xác hơn, HEADlà "con trỏ tới một nhánh" (tệp thực tế trong repo cục bộ của bạn thường chứa chuỗi ref: refs/heads/master, ví dụ ... trừ khi nó "tách rời", đó là một thứ hoàn toàn khác). Tuy nhiên, có một loại lỗi trong cách clonediễn giải "ĐẦU từ xa": các giao thức chuyển giao hoàn toàn không thể gửi một nhánh gián tiếp, chỉ là một SHA-1 thô, vì vậy git có một loại bùn làm cho "phần lớn hoạt động". Thỉnh thoảng lại có người tình cờ gặp một trường hợp kỳ lạ. Tôi ước gì git không tạo ra remotes/origin/HEADchút nào, đặc biệt là khi nó phát ra sai ...
torek

2

Tôi nghĩ rằng ký hiệu gạch chéo git này có thể được hiểu rõ nhất bằng cách nhìn vào bên trong .gitthư mục của bạn .


Ví dụ, đây là một cây viết tắt của .git của tôi cho cơ sở nguồn LibreOffice.

Trong linux sudo apt-get install tree rất hữu ích để xem điều này.
Trong Windows tôi nghĩ rằngtree lệnh vẫn có thể hoạt động.

Cuộn xuống và xem các ref (còn gọi là 'tài liệu tham khảo') ở gần cuối:

$ tree  
.  
├── branches  
├── config  
├── description  
├── FETCH_HEAD  
├── gitk.cache  
├── HEAD  
├── hooks  
│   ├── applypatch-msg.sample  
    ...
├── index  
├── info  
│   └── exclude  
├── logs  
│   ├── HEAD  
│   └── refs  
│       ├── heads  
│       │   ├── master  
│       │   └── remotes  
│       │       └── origin  
│       └── remotes  
│           └── origin  
│               ├── distro  
│               │   ├── cib  
│               │   │   └── libreoffice-6-0  
│               │   ├── collabora  
│               │   │   └── cp-6.0  
│               │   └── lhm  
│               │       └── libreoffice-5-2+backports  
│               ├── HEAD  
│               ├── libreoffice-6-2  
│               ├── master  
│               └── private  
│                   └── mst  
│                       └── sw_redlinehide_4a  
├── objects  
│   ├── info  
│   └── pack  
│       ├── pack-b80087dc57e2b3315f449ca0f1aaa91987bf0c5e.idx  
│       ├── pack-b80087dc57e2b3315f449ca0f1aaa91987bf0c5e.pack  
│       ├── pack-eb4e6808029e712d8d9c2671accbbd98aaeb9a04.idx  
│       └── pack-eb4e6808029e712d8d9c2671accbbd98aaeb9a04.pack  
├── ORIG_HEAD  
├── packed-refs  
└── refs  
    ├── heads  
    │   ├── master  
    │   └── remotes  
    │       └── origin  
    ├── remotes  
    │   └── origin  
    │       ├── distro  
    │       │   ├── cib  
    │       │   │   └── libreoffice-6-0  
    │       │   ├── collabora  
    │       │   │   └── cp-6.0  
    │       │   └── lhm  
    │       │       └── libreoffice-5-2+backports  
    │       ├── HEAD  
    │       ├── libreoffice-6-2  
    │       ├── master  
    │       └── private  
    │           └── mst  
    │               └── sw_redlinehide_4a  
    └── tags  
        └── libreoffice-6-2-branch-point  

32 directories, 45 files

Nó có thể đã ít gây nhầm lẫn hơn nếu nó được đặt ra như thế này, nhưng nó không phải là:

repositories (i.e. independent trees)
├──local
│  └──master
│
└──origin1
│  └──master
└──origin2
   └──master

Chúng tôi có ba loại tài liệu tham khảo cơ bản: người đứng đầu , điều khiển từ xathẻ .

  • .git / refs / người đứng đầu tổ chức địa phương của chúng tôi chủ .

  • .git / refs / điều khiển từ xa có thể chứa một số điều khiển từ xa, mặc dù tại thời điểm này chúng ta chỉ có nguồn gốc trong đó.

  • .git / refs / tags (được thảo luận ở nơi khác).

gốc như vậy, là một và chỉ từ xa của chúng tôi. Nó giữ nguồn gốc / chủ .


Chúng tôi thấy rằng chúng tôi có 2 ĐẦU (con trỏ tới các nhánh hiện tại), một cục bộ và một điều khiển từ xa:

$ cat .git/HEAD                        #         local:  HEAD -> master
ref: refs/heads/master

$ cat .git/refs/remotes/origin/HEAD    # remote origin:  HEAD -> master
ref: refs/remotes/origin/master

Nếu bạn liệt kê các chi nhánh của bạn :

$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/aoo/aw080
  remotes/origin/aoo/trunk
  remotes/origin/distro/capgemini/cg-4.1
  remotes/origin/distro/cib/libreoffice-5-0
  remotes/origin/distro/cib/libreoffice-5-1
  remotes/origin/distro/cib/libreoffice-5-2
  ...
  • Chi nhánh đầu tiên được liệt kê ( chính ) là nhánh duy nhất không phải là điều khiển từ xa. Vì vậy, trong trường hợp này, chúng tôi có một chi nhánh địa phương. Đây là nơi chúng ta sẽ bắt đầu công việc của mình từ đó, cho các chi nhánh mới của chúng ta và các cam kết tiếp theo.

Tiếp theo, bạn có thể có nhiều chi nhánh theo dõi từ xa, và chúng tôi làm ở đây. Bạn biết đây là những nhánh theo dõi từ xa vì chúng có tiền tố là ' điều khiển từ xa / '. Những cái được hiển thị ở đây là cho nguồn gốc có tên từ xa.

  • Vì vậy, dòng thứ hai là con trỏ nhánh hiện tại của nguồn gốc . Từ xa / nguồn gốc: CHÍNH - điểm đến -> chính. Điều này cho thấy trong kho lưu trữ từ xa, nhánh hiện tại là nhánh của chúng có tên là master , (không bị nhầm lẫn với nhánh cục bộ của chúng ta có tên master ).

  • Các nhánh còn lại không được tìm thấy trong .git / refs / cây của bạn, nhưng thay vào đó bạn sẽ tìm thấy chúng trong .git/packed-refs .

Khi nào chúng ta git fetch chúng tôi tải thay đổi từ kho lưu trữ từ xa, vào kho theo dõi từ xa của chúng tôi.

Khi nào chúng ta hợp nhất, chúng tôi hợp nhất các thay đổi trong kho lưu trữ theo dõi từ xa cục bộ này vào nhánh hoặc nhánh cục bộ đang hoạt động của chúng tôi, trong trường hợp này vào nhánh chính của chúng tôi.

(Khi nào chúng ta kéo, chúng tôi thực hiện cả hai bước này trong một thao tác.)


Thật thú vị khi lưu ý các UUID cục bộtừ xa này cho chủ hiện đang trỏ đến cùng một nút (còn gọi là 'commit'):

$ cat refs/heads/master                   # local         master
1ca409292272632f443733450313de5a82c54a9c

$ cat refs/remotes/origin/master          # remote origin master
1ca409292272632f443733450313de5a82c54a9c

Vì vậy, chủ địa phương của chúng tôi trỏ đến cùng một nơi với chủ gốc của điều khiển từ xa:

[local] master = [remote] origin master

Cuối cùng, tôi nghĩ cũng hữu ích khi xem qua .git/packed-refs

$ cat packed-refs 
# pack-refs with: peeled fully-peeled 
3c1d4742e649fe9c8aed8c2817fe3e1f3364f298 refs/remotes/origin/aoo/aw080
e87c8b7922e9a73e0abb7f9a7a47c9ac3374a826 refs/remotes/origin/aoo/trunk
b70fdffb041c12f124dcc0822b61bf3450e53137 refs/remotes/origin/distro/capgemini/cg-4.1
5dbc3f1754809b9489faaf380b1a4bdbcfbb6205 refs/remotes/origin/distro/cib/libreoffice-5-0
cfdbc96ca47d68d6785fd21829a8d61f49d6e591 refs/remotes/origin/distro/cib/libreoffice-5-1
5189c8c47461ef09739086e55512fc6a10245273 refs/remotes/origin/distro/cib/libreoffice-5-2
3bee5917569ca8e6ee3b086458f5b1a917b88ca1 refs/remotes/origin/distro/cib/libreoffice-5-3
92fbe703f9ca480d3a2b8610d87e991c729edf77 refs/remotes/origin/distro/cib/libreoffice-5-4
05c0a5df66cc69d75280f05b804cf82f3387d42b refs/remotes/origin/distro/cib/libreoffice-6-0
7fe193e759b24b90852e6e327115b77114d7b119 refs/remotes/origin/distro/cib/libreoffice-6-1
8187f7aa413e7ef7b377eea2b057d336bf256867 refs/remotes/origin/distro/collabora/cd-5.3
7a6b608591e21ef61dc05cff9fc58da531035755 refs/remotes/origin/distro/collabora/cd-5.3-3.1
....

Không nghi ngờ gì điều này để lại nhiều câu hỏi hơn câu trả lời, nhưng tôi nghĩ nó có thể bắt đầu giúp bạn trả lời câu hỏi của riêng bạn về những gì.

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.