Các thuật ngữ Git dễ gây nhầm lẫn
(jvns.ca)- Git có nhiều thuật ngữ bị trùng lặp và tái sử dụng dễ gây nhầm lẫn ngay cả khi đã dùng lâu, nên chỉ học thuộc lệnh thôi thì khó dự đoán hành vi thực tế
- Cùng một từ hoặc ký hiệu như
HEAD,heads, detached HEAD,ours/theirs,../...có thể đổi nghĩa tùy theo ngữ cảnh index,staged,cachedđều liên quan đến.git/index, nhưngreset,revert,restoredù tên nghe giống nhau lại có tác động khác nhau đến lịch sử commit, working tree và con trỏ branch- Việc
maintrack remote và remote-tracking branch nhưorigin/mainlà hai chuyện riêng, còncheckoutgộp cả chuyển branch lẫn khôi phục file vào cùng một lệnh - Để hiểu Git, cần nhìn vào mô hình nội bộ nơi branch, reference, commit, index và trạng thái theo dõi remote liên kết với nhau, thay vì chỉ nhìn từng lệnh riêng lẻ
HEAD, branch, detached HEAD
- Trong Git, heads chỉ các branch; về mặt nội bộ, branch được lưu trong thư mục
.git/refs/heads- Bảng thuật ngữ chính thức của Git phân biệt branch là toàn bộ các commit phía trên nó, còn head là commit mới nhất, nhưng có thể xem đây là hai cách nhìn cùng một đối tượng
HEADtrỏ đến branch hiện tại và được lưu trong.git/HEAD- Cách diễn đạt “
headlà branch, cònHEADlà branch hiện tại” tự nó đã cho thấy sự rối rắm trong thuật ngữ Git
- Cách diễn đạt “
- detached HEAD state là trạng thái trong đó
HEADkhông trỏ đến branch mà trỏ trực tiếp đến một commit ID- Khi checkout một tag, vì tag không phải branch nên có thể rơi vào trạng thái detached HEAD
- Ở trạng thái này,
git pullkhông hoạt động, vàgit pushcũng không hoạt động trừ khi dùng cách đặc biệt - Có thể dùng
git commit,git merge,git rebase,git cherry-pick, nhưng các commit mới có thể không được nối với branch nào nên sau này khó tìm lại - Có thể thoát khỏi trạng thái detached HEAD bằng cách tạo branch mới hoặc chuyển sang branch hiện có
ours và theirs thay đổi giữa merge và rebase
- Khi giải quyết conflict,
git checkout --ours file.txtchọn file phía “ours”, nhưng điểm quy chiếu của merge và rebase lại khác nhau - Trong merge, branch hiện tại là
ours, branch được merge vào làtheirs- Ví dụ: sau
git checkout merge-into-ours, chạygit merge from-theirsthì branch hiện tại trở thànhours
- Ví dụ: sau
- Trong rebase, branch hiện tại là
theirs, branch đích của rebase làours- Ví dụ: sau
git checkout theirs, chạygit rebase oursthì branch đích trở thànhours
- Ví dụ: sau
- Khác biệt này liên quan đến cách
git rebase mainbên trong lặp lại việc merge các commit của branch hiện tại vào bản sao của branchmain- Ví dụ liên quan nằm trong shell script triển khai
git rebasebằnggit merge
- Ví dụ liên quan nằm trong shell script triển khai
- ourstheirs giải thích ngắn gọn các thuật ngữ
oursvàtheirs- “current change” và “incoming change” trong VSCode cũng có thể gây nhầm lẫn theo cách tương tự
Thông báo trạng thái remote và fast-forward
Your branch is up to date with 'origin/main'không có nghĩa làmainhiện tại đang mới nhất so với remote- Nó có nghĩa là branch local giống với
origin/maintại thời điểmgit fetchhoặcgit pullgần nhất - Nếu lần fetch gần nhất là 5 ngày trước, thì nó chỉ “mới nhất theo mốc 5 ngày trước”
- Nó có nghĩa là branch local giống với
- Git lưu thông tin thời điểm fetch gần đây trong reflog, nhưng thông báo trạng thái không hiển thị thời gian “theo lần fetch gần nhất”
can be fast-forwardedcó nghĩa là branch remote đang đi trước branch local, local không có commit riêng, nên có thể chỉ cần di chuyển con trỏ về phía trước- Ví dụ: nếu
mainlàA-B-C, cònorigin/mainlàA-B-C-D-E, thì saugit pullcả hai đều thànhA-B-C-D-E - Trong trường hợp này không có khả năng xảy ra merge conflict
- Ví dụ: nếu
- Khi không thể fast-forward, nghĩa là hai branch đã tách nhánh
- Ví dụ: nếu
maincó commitXkhông có trongorigin/main, cònorigin/maincóD,Ekhông có trongmain, thì không thể fast-forward - Khi đó Git hiển thị rằng hai branch đang ở trạng thái diverged và mỗi bên có số commit khác nhau
- Ví dụ: nếu
Cú pháp chọn commit: ^, ~, .., ...
HEAD^vàHEAD~đều trỏ đến commit liền trước 1 bướcHEAD^^^,HEAD~~~,HEAD~3đều trỏ đến commit trước đó 3 bước
- Với commit có nhiều parent như merge commit, ý nghĩa của
HEAD^2,HEAD^3sẽ khácHEAD^là parent thứ nhấtHEAD^2là parent thứ haiHEAD^3là parent thứ baHEAD~3nghĩa là parent của parent của parent, nên khác vớiHEAD^3
git log main..testvàgit log main...testcũng hoạt động khác nhaumain..testhiển thị các commit chỉ có trongtesttest..mainhiển thị các commit chỉ có trongmainmain...testhiển thị các commit chỉ có ở một trong hai phía
- Trong
git diff,..và...được diễn giải khác vớigit loggit diff test..mainso sánh bao gồm cả thay đổi phíatestlẫn thay đổi phíamaingit diff test...mainso sánh tổ tiên chung với đầu mút phíamain, chỉ hiển thị diff của một phía
- Sự rối rắm của ký hiệu dấu chấm cũng được bàn thêm trong pain in dots
reference, refspec, tree-ish
- Trong Git, reference được dùng với nhiều nghĩa
- Branch và tag như
main,v0.2 HEAD, thứ trỏ đến branch hiện tại- Biểu thức được diễn giải thành commit ID như
HEAD^^^
- Branch và tag như
- Tài liệu Git gọi các biểu thức như
HEAD^^^một cách chính xác là “revision parameters”, nhưng trong sử dụng hằng ngày chúng có thể được đối xử như reference - symbolic reference là reference trỏ đến một reference khác, như
HEADHEADlà khái niệm trung tâm có ảnh hưởng lớn đến hành vi của các lệnh cốt lõi trong Git
- Cấu hình remote trong
.git/configchứa refspec- Ví dụ:
+refs/heads/main:refs/remotes/origin/main - Nhiều trường hợp chỉ dùng nguyên giá trị mà
git clonehoặcgit remote addmặc định tạo ra
- Ví dụ:
tree-ishchỉ những đối tượng có thể làmTHINGtronggit checkout THING .- Commit ID
- Reference đến commit như
main,HEAD^^,v0.3.2 - Thư mục con bên trong commit như
main:./docs - Trong thực tế, nhiều khi có thể hiểu đơn giản là “commit hoặc reference đến commit”
index, staged, cached
index,staged,cachedđều liên quan đến.git/index.git/indexlà file được dùng khi stage thay đổi bằnggit add
- Nhiều cách gọi cùng một đối tượng nằm rải rác trong nhiều lệnh
git diff --cachedgit rm --cachedgit diff --staged.git/index
- Tuy nhiên các flag
--indexvà--cachedkhông phải lúc nào cũng có cùng nghĩa- Bài viết của Junio Hamano, maintainer chính của Git, giải thích khác biệt chi tiết
- Vì lý do hiệu năng, index cũng liệt kê cả untracked files, nhưng thông thường staging area không được xem là bao gồm untracked files
reset, revert, restore
reset,revert,restorelà những từ nghe giống nhau nhưng trong Git chúng tác động đến các đối tượng khác nhaugit revert COMMITtạo một commit mới trên branch hiện tại để thực hiện thao tác ngược lại vớiCOMMIT- Nếu
COMMITđã thêm 3 dòng, commit mới sẽ xóa 3 dòng đó
- Nếu
git reset --hard COMMITcưỡng bức đưa branch hiện tại quay về thời điểmCOMMIT- Đây là thao tác rất nguy hiểm vì xóa các thay đổi mới sau
COMMIT
- Đây là thao tác rất nguy hiểm vì xóa các thay đổi mới sau
git restore --source=COMMIT PATHđưa các file trongPATHvề trạng thái tại thời điểmCOMMIT- Nó không thay đổi file khác hay lịch sử commit
- Khi dùng riêng,
git reset --hardvàgit restore .thường hoạt động khá giống nhau, nhưnggit reset --hard COMMITvàgit restore --source COMMIT .hoạt động hoàn toàn khác nhau
track, remote-tracking branch, untracked files
- Git dùng từ track theo ba cách
Untracked files:tronggit statuschỉ các file Git không quản lý và không được đưa vào commit- Remote-tracking branch như
origin/mainlà reference local chứa commit ID màmaintrên remoteorigintrỏ tới tại thời điểmgit pullhoặcgit fetchgần nhất - Một branch local có thể được cấu hình để track một branch remote, như trong “branch foo set up to track remote branch bar from origin”
- Nói
mainlà branch track remote và nóiorigin/mainlà remote-tracking branch là hai chuyện khác nhau mainlà branch thật nên có thể tạo commit và merge trên đó- Nếu được cấu hình trong
.git/configđể trackmaintrên remote, có thể dùnggit pullvàgit pushthuận tiện hơn
- Nếu được cấu hình trong
origin/maindù có tên là “remote-tracking branch” nhưng không phải branch thông thường- Không thể commit trực tiếp lên đó
- Nó chỉ được cập nhật khi lấy trạng thái
mainmới nhất từ remote bằnggit pullhoặcgit fetch
checkout, reflog, merge/rebase/cherry-pick
git checkoutgộp hai thao tác khác nhau vào cùng một lệnhgit checkout BRANCHchuyển branchgit checkout file.txtbỏ các thay đổi unstaged củafile.txt
- Để giảm nhầm lẫn này, Git đã tách chức năng thành
git switchvàgit restore, nhưngcheckoutcũ vẫn có thể dùng refloglà reference log, tức bản ghi một reference từng trỏ đến đâu trong quá khứ- Reference là thuật ngữ bao quát bao gồm branch, tag và
HEAD - Reflog có thể giúp thoát khỏi những tình huống Git rất tệ, chẳng hạn lỡ xóa một branch quan trọng
- Reference là thuật ngữ bao quát bao gồm branch, tag và
- merge, rebase, cherry-pick khác nhau ở cách hợp nhất commit
- merge tạo một commit mới để hợp nhất hai branch
- rebase sao chép từng commit của branch hiện tại lên trên branch đích
- cherry-pick giống rebase nhưng cú pháp khác, và sao chép commit vào branch hiện tại
git rebase --onto main otherbranch mybranchcó thể được dùng khi chỉ muốn chuyển một phần commit củamybranchlên trênmain- Trong cấu trúc ví dụ, có thể dùng khi muốn rebase chỉ
F,Glên trênmain - Đây là cú pháp khó nhớ vì có tới ba tên branch
- Trong cấu trúc ví dụ, có thể dùng khi muốn rebase chỉ
commit và các thuật ngữ dễ nhầm lẫn khác
committrong Git được dùng vừa là động từ vừa là danh từ- Động từ: “hãy commit thường xuyên”
- Danh từ: commit mới nhất của
main
- Có thể nhìn Git commit theo ba cách
- Snapshot trạng thái hiện tại của toàn bộ file
- Diff so với commit cha
- History của tất cả commit trước đó
- Mỗi lệnh xử lý commit theo cách khác nhau
git showxem commit như diffgit logxem commit như historygit restorexem commit như snapshot
blob,tree,origin,upstream,downstream, quan hệ giữafetchvàpull,stash,worktree,subtree,submodulecũng nằm trong các thuật ngữ Git dễ gây nhầm lẫn- Trong thuật ngữ GitHub, “pull request”, “squash and merge”, “rebase and merge” được xem là những ví dụ gây nhầm lẫn
Ba trục nhầm lẫn lặp đi lặp lại
- Những thuật ngữ Git đặc biệt gây nhầm lẫn có thể rút gọn thành ba điểm
headlà branch, cònHEADlà branch hiện tại- “remote tracking branch” và “branch that tracks a remote” là hai thứ khác nhau
index,staged,cachedđều chỉ cùng một đối tượng
- Bài viết năm 2012 the most confusing git terminology cũng bàn về cách thuật ngữ Git liên hệ với thuật ngữ CVS và Subversion
- Sự rối rắm trong thuật ngữ Git không chỉ nằm ở vài tính năng đặc biệt mà lặp lại trên toàn bộ các chức năng cốt lõi
- Đặc biệt khi nói về branch, “tracking” được dùng theo nhiều cách nên lúc mới nhìn rất khó nhận ra khác biệt
- Một số giải thích có nhắc đến các ngóc ngách ít gặp của Git, nên vẫn có lưu ý rằng có thể có sai sót
1 bình luận
Ý kiến trên Hacker News
Tên branch,
HEAD, tag đều là con trỏ.HEADtrỏ tới commit bạn đang xem hiện tại, còn tên branch nhưmy-featuretrỏ tới commit mới nhất của branch đó. Nếu đang ởmainvà chạygit checkout -b my-feature, thìmain,my-feature,HEADđều sẽ trỏ tới commit mới nhất củamainMỗi lần commit trên
my-branch,HEADvàmy-branchsẽ di chuyển để trỏ tới commit mới. detached HEAD nghĩa là không có branch nào trỏ tới commit màHEADđang trỏ tới. Khác biệt giữa tag và branch là tag trỏ tới một commit cụ thể và không di chuyểnMột điều khác từng khiến tôi bối rối là lý do nhiều lệnh trông có vẻ không nhất quán: Git giả định các đối số mặc định.
git checkout file.txttương đươnggit checkout HEAD -- file.txt, còn khi đang ởmy-branch,git rebase maintương đươnggit rebase main my-branch. Tuy nhiên dạng sau có thể chạy từ một branch khácCuối cùng, khi mọi thứ rối tung, lệnh giúp bạn thoát khỏi bất kỳ trạng thái kỳ lạ nào là
git reflog. Nó hiển thị tất cả các commit màHEADtừng trỏ tới. Dù vậy, thật đáng mừng khi Git thừa nhận sự rối rắm này và đang tạo ra các lệnh có giao diện ít bất ngờ hơn, đơn giản hơnreflogMột điểm mà nhiều người dùng Git không hay nghĩ tới là các ref của branch hoặc tag từ remote đã fetch về cũng đều là ref, nên ở bất cứ nơi nào có thể dùng tên ref thì đều có thể tham chiếu tới chúng
Ví dụ nếu muốn nói “tôi không quan tâm branch này đang có gì, đừng fast-forward, đừng merge, đừng rebase, cứ ghi đè branch local bằng nội dung remote”, bạn có thể làm như sau:
git checkout foo,git reset --hard origin/fooHEADkhông trực tiếp trỏ tới commit; thông thường nó trỏ tới một con trỏ branch nhưmy-branch, rồi con trỏ branch đó mới trỏ tới commit. Trạng thái detached HEAD là ngoại lệKhi commit trên
my-branch, không phải cảHEADvàmy-branchđều di chuyển sang commit mới;HEADvẫn tiếp tục trỏ tới con trỏmy-branch, còn chỉmy-branchdi chuyển để trỏ tới commit mới. Tất nhiên nếu đi theoHEADquamy-branchtới commit, bạn sẽ tới commit mớidetached HEAD là trạng thái
HEADtrỏ trực tiếp tới commit thay vì con trỏ branch. Ngay cả trong trạng thái detached HEAD, cảHEADvà con trỏ branch vẫn có thể cùng trỏ tới commit mới nhất. Khi xemgit log --decorate, thay vì kiểu thông thường(HEAD -> my-branch), ở commit mới nhất thường sẽ hiện như(HEAD, my-branch)Ngược lại, annotated tag có thể chứa message, timestamp, SHA, v.v. Chúng là các đối tượng Git đúng nghĩa và hoạt động khá giống đối tượng commit, nhưng thường vẫn tham chiếu tới một đối tượng Git khác, đa số là commit
git rev-parse HEADvà sao chép chuỗi đó vào nơi an toànNó tạo cảm giác yên tâm rằng bạn đã đánh dấu chính xác trạng thái cuối cùng mà mình chắc chắn là ổn. Thường thì bạn có thể quay lại trạng thái tốt cuối cùng, chứ không phải một điểm nào đó sau vài bước đi vào hỗn loạn. Tất nhiên với điều kiện là bạn không bất cẩn dùng những thứ như
git gchaygit filter-branchNghe như đùa nhưng không phải đùa: nói rằng muốn dùng Git thì thật sự cần bằng khoa học máy tính cũng không hẳn sai. Tôi đồng ý rằng các đối số mặc định của Git tạo ra trải nghiệm sử dụng rất thiếu nhất quán
git checkout .,git reset --hard/soft,git cleanupđều trông cực kỳ giống nhau nhưng thực tế lại rất khác. Dù vậy tôi vẫn thích Git hơn Perforce hay SVN. Trước đây tôi từng thích Mercurial hơn một chút, nhưng không biết bây giờ còn vậy khônggit refloglà vua và cho thấy sự thậtTôi nhớ đã đọc đâu đó rằng Linus Torvalds ngạc nhiên khi mọi người bắt đầu dùng Git trực tiếp thay vì đặt một lớp thân thiện hơn lên trên. Nếu ngành này có khả năng tự nhìn lại, có lẽ chúng ta đã thừa nhận việc chọn Git là sai lầm và chuyển sang hệ thống quản lý phiên bản khác. Đừng lãng phí vô số thời gian vào một công cụ mà về cơ bản chỉ là lưu trữ văn bản
Tất nhiên nó có thể tốt hơn nữa. Nhưng sự ghét bỏ dành cho Git luôn làm tôi ngạc nhiên. Git là một công cụ tuyệt vời, và đi trước rất xa so với các công cụ dành cho người không phải lập trình viên như Word hay Google Docs
Có lẽ vì tôi đủ lớn tuổi để nhớ thời Subversion còn là vua
Hằng tuần tôi thấy đồng nghiệp bối rối vì Git, thấy các bài cầu cứu trên mạng, rồi lại thấy những bài cố gắng giải thích lại những thứ lẽ ra phải đơn giản như bài này
Trong thời gian viết code, tôi không nhớ có ai lãng phí hàng giờ để đảo ngược mớ hỗn độn do chính họ tạo ra trong SVN, TFVC, Perforce, v.v.
Công cụ tồn tại để làm cuộc sống dễ hơn. Nếu không làm được điều đó thì không đáng để bỏ thời gian
Mình vẫn ước là còn có sự đa dạng như vậy. Độc canh Git cũng có nghĩa là bất cứ thứ gì muốn thay thế Git trước hết phải triển khai lại Git. Vì thế chúng ta gần như bị buộc chặt vào Git mãi mãi, giống như ASCII hay phím Scroll Lock
Nỗi lo cốt lõi là GitHub quá tốt, nên trừ khi GitHub tách Git khỏi engine quản lý ký tự và cho phép dùng các engine khác, chúng ta sẽ bị buộc vào Git
https://trolololo.xyz/github
https://news.ycombinator.com/item?id=38098109
Chúng là những thuật ngữ kiểu abstraction bị rò rỉ
cache, đây là thuật ngữ mang tính khoa học máy tính nhấtSau đó có vẻ Junio đổi nó thành
index, chuyên biệt hơn cho hệ thống quản lý phiên bản phân tán, còn đa số người dùng gọi nó là staging area. Giờ quá trình tiến hóa thuật ngữ này đã hóa thạch trong UI và nội bộ của Gitpullorigin/masterkhông phải là master trên origin, mà là commit màorigin/masterđược biết lần cuối đang trỏ tới. Giá trị này được cập nhật khifetch, vàpulltự động thực hiệnfetchNhìn
ls -l .git/refs/remotes/origin/mastersẽ thấyorigin/masterchỉ là một file trên hệ thống của bạn. Bạn cũng có thể xem nó thay đổi lúc nào. Nó không tự cập nhật như phép thuậtKhi chạy
git fetch origin, nếu có thay đổi thì timestamp và nội dung sẽ đổi. Có thể kiểm tra bằngcat .git/refs/remotes/origin/masterNền tảng của Git rất đơn giản, đến mức các cấu trúc dữ liệu cốt lõi và vài thao tác có thể được triển khai trong một ngày. Biết điều này thực sự rất đáng giá. Không hiểu bằng cách nào mà Git đã tạo ra một giao diện người dùng cực kỳ phức tạp trên một lõi khá đơn giản
mastercục bộ. Thường thì không thể push lênmaster, hoặc dù sao tôi cũng không muốn làm việc trực tiếp trênmaster. Vậy thì chẳng có lý do gì để giữ một branchmastercục bộ có thể thay đổiVì thế chỉ cần cập nhật
origin/master, vàfetchlà đủgit fetch && git pullĐang chờ 3 năm nữa nghỉ hưu để rửa tay khỏi đống rác hỏng hóc này
git status, và thêm flag--porcelainvào thì thật sự hữu ích. Nó tạo ra output gọn hơn và dễ parse bằng chương trình hơnTôi bắt đầu tò mò không biết có bao nhiêu lệnh có output dễ đọc hơn cho máy, rồi cuối cùng đọc đến trang “Git Internals - Plumbing and Porcelain” của git-scm. Tóm lại, ngay từ đầu Git được viết giống một bộ công cụ để xử lý quản lý phiên bản hơn là một hệ thống quản lý phiên bản bóng bẩy
Nhiều người dùng Git từ sớm đã học các tác vụ quản lý phiên bản bằng các lệnh mức thấp này, rồi truyền bá workflow đó cho người khác. Đây là tầng plumbing. Về sau Git tạo ra một tầng được trau chuốt hơn, gọi là porcelain
Tôi vẫn chưa hoàn toàn biết lệnh nào thuộc tầng nào, nhưng điều này đã giúp tôi hiểu các workflow mới được khuyến nghị trong vài năm gần đây. Nó cũng giúp tôi phán đoán tốt hơn khi thay đổi workflow của mình
https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Po...
Đáng tiếc là để làm nó nhanh hơn, họ đã hard-code UI đó, nhưng lại không cải thiện nó
Nhìn lại thì lúc mới bắt đầu chắc hẳn tôi đã cực kỳ bối rối, nhưng có lẽ đã giả vờ là không để trông ngầu hơn
https://news.ycombinator.com/item?id=28143078
“Your branch is up to date with ‘origin/main’” thực ra hơi dễ gây hiểu lầm. Có thể hiểu là nhánh
mainđang mới nhất, nhưng thực tế không phải vậyTuy nhiên cũng không cần phải quá “nói cho thật chính xác” ở đây. Chẳng phải bài toán hai vị tướng áp dụng trong trường hợp này sao? Nếu soi thật kỹ thì không thể biết ngay đúng khoảnh khắc này có “mới nhất” hay không. Kể cả có
fetchtrướcstatusthì cũng vậyVậy kỳ vọng hợp lý là gì? Đại khái là ref trong cơ sở dữ liệu object trên máy mình, ở lần kiểm tra cuối cùng, giống với ref trong một cơ sở dữ liệu object khác ở tận đâu đó
Một lệnh gọi
statusđơn giản không thể thực hiệnfetchqua mạng, hay lần nào cũng nhắc lại cho bạn nguyên lý cơ bản của công cụ đang dùng. Cá nhân tôi nghĩ vậy. Nhưng đáng ngạc nhiên là rất nhiều bình luận trong câu trả lời trên StackOverflow lại cho rằng cần đúng hai điều đóCách diễn đạt như “is up to date with the origin’s main as of your last fetch 5 days ago” thì hợp lý hơn một chút. Vì nó chỉ cho biết lần
fetchcuối cùng cách đây bao lâu[1] https://stackoverflow.com/questions/27828404/why-does-git-st...
Một điều nữa: tôi từng nghĩ
ORIG_HEADcó liên quan đến “head của origin” nhưFETCH_HEAD. Nhưng không phải. “pseudoref” này có vẻ được dùng làm điểm lưu trước các thao tác ghi lại lịch sử phức tạp hơn như rebase, và được triển khai trước khi có reflog. Có lẽ nó có nghĩa là “original head”“Your branch is up to date with ‘origin/main’” về mặt kỹ thuật là đúng, nhưng cụm up to date nếu đọc lướt thì gợi ra hai điều:
maingiốngorigin/main, vàorigin/maincũng đang mới nhất, tức là có cảm giác nó đã được cập nhật trong lúc chạy lệnh hoặc được tự động giữ ở trạng thái mới nhất và lần đồng bộ gần đây đã thành côngĐây không phải là tín hiệu máy đọc cần đúng trong một chu kỳ CPU, mà là thông báo trạng thái hiển thị cho người dùng. Không cần lôi lý thuyết mạng vào thì cách hiểu như vậy vẫn hợp lý
“Up to date” gần với nghĩa đã bắt kịp theo thời gian hơn là theo không gian. Vị trí của nhánh cục bộ gần với “nhánh này đang trỏ tới đâu”, tức không gian; còn trạng thái ref từ xa gần với “lần cuối tôi cập nhật ref từ xa là khi nào”, tức thời gian. Tất nhiên điều này rất chủ quan và cả hai đều có thể mang cả hai nghĩa
Câu chữ tốt hơn có thể là “Your branch matches origin/main”, “Your branch’s head is the same as origin/main”, “Your branch is pointing to the same commit as origin/main”. Đó là sự đánh đổi giữa rõ ràng và dài dòng. Cũng có thể thêm trong ngoặc “remote ref last updated 5 days ago” như đề xuất của tác giả
statusthực hiệnfetchqua mạng là điều khó chịu. Tôi cho rằng tác vụ mạng phải là tường minh, không nên là ngầm định. Khi chạygit status, tôi muốn biết trạng thái kho lưu trữ của mình trên hệ thống tệpNếu muốn biết chuyện gì đang xảy ra ở remote khác, tôi có thể tự
fetchrồi so sánhstatus. Có thể có race condition trong lúc thông tin được in ra terminal, nhưng đó là một khoảng thời gian rất nhỏNhìn chung điều này có nghĩa là muốn có
fetch. Bài toán hai vị tướng chỉ áp dụng cho phía remote. Nếu remote không nhận được xác nhận rằng client đã nhận dữ liệu, nó có thể tiếp tục truyền lại một thời gian. Đó không phải vấn đề của clientNếu client không nhận được dữ liệu từ server, hành vi đúng có lẽ là đứng chờ rồi sau khi timeout thì in lỗi; hiện tại
fetchcó lẽ cũng làm như vậyCông cụ này thường được chia sẻ, và ở đây cũng rất phù hợp. Nó trực quan hóa mô hình nội bộ của Git và tác động của nhiều lệnh
https://learngitbranching.js.org/
Tôi học được nhiều hơn trong 10 phút dùng công cụ này so với khoảng 10 năm kinh nghiệm Git trước đó. Rất khuyến nghị
“pull” là thao tác hợp nhất thay đổi từ remote vào kho lưu trữ cục bộ. Thứ người dùng thực sự yêu cầu là server hãy hợp nhất thay đổi từ remote của họ vào một nhánh nào đó. “merge request” của GitLab mới là cách gọi đúng
Tôi từng thấy có người
fetchxong thì thấy commit biến mất. Đó là vì kho lưu trữ đã đi lùi theo thời gian nên chúng bị ẩn đi. Git giấu các chi tiết như vậy trongstatus; nếu không dùnggit-prompthaypowerline-shellthì chẳng khác nào làm việc trong bóng tốigit-request-pull(1)là mỗi chúng ta sẽ có một kho Git riêng ở những nơi như kernel.org/git hoặc redhat.com/git, rồi gửi email yêu cầu nhau pull từ các kho nằm trên những server, tổ chức, domain khác nhauGitHub lấy cảm hứng từ lệnh
request-pullcủa Git, nhưng diễn giải lại thành việc hợp nhất từ một kho GitHub này sang một kho GitHub khácÍt nhất tôi luôn đọc theo cách đó
Tóm lại, đó không phải là yêu cầu gửi tới server, mà là yêu cầu gửi tới một người khác. Bạn yêu cầu người đó pull nhánh của mình để xem xét các thay đổi mà bạn muốn đóng góp cho dự án
[0] https://git-scm.com/book/en/v2/Distributed-Git-Contributing-...