Linus Torvalds có ý nghĩa gì khi anh ta nói rằng Git Tiết không bao giờ theo dõi một tập tin?


283

Trích dẫn Linus Torvalds khi được hỏi Git có thể xử lý bao nhiêu tệp trong Tech Talk của mình tại Google năm 2007 (43:09):

Sọ Git theo dõi nội dung của bạn. Nó không bao giờ theo dõi một tập tin duy nhất. Bạn không thể theo dõi một tập tin trong Git. Những gì bạn có thể làm là bạn có thể theo dõi một dự án có một tệp duy nhất, nhưng nếu dự án của bạn có một tệp duy nhất, chắc chắn làm điều đó và bạn có thể làm điều đó, nhưng nếu bạn theo dõi 10.000 tệp, Git sẽ không bao giờ xem đó là các tệp riêng lẻ. Git nghĩ mọi thứ là nội dung đầy đủ. Tất cả lịch sử trong Git đều dựa trên lịch sử của toàn bộ dự án

(Bảng điểm ở đây .)

Tuy nhiên, khi bạn nhảy vào cuốn sách Git , điều đầu tiên bạn đang nói là một tập tin trong Git có thể được hoặc theo dõi hoặc untracked . Hơn nữa, dường như toàn bộ trải nghiệm Git đều hướng đến phiên bản tệp. Khi sử dụng git diffhoặc git statusđầu ra được trình bày trên cơ sở mỗi tệp. Khi sử dụng, git addbạn cũng có thể chọn trên cơ sở mỗi tệp. Bạn thậm chí có thể xem lại lịch sử trên cơ sở tập tin và nhanh như chớp.

Tuyên bố này nên được giải thích như thế nào? Về mặt theo dõi tệp, Git khác với các hệ thống kiểm soát nguồn khác, chẳng hạn như CVS như thế nào?


20
reddit.com/r/git/comments/5xmrkv/what_is_a_snapshot_in_git - "Hiện tại bạn đang ở đâu, tôi nghi ngờ điều quan trọng hơn cần nhận ra là có sự khác biệt giữa cách Git trình bày các tệp cho người dùng và cách nó xử lý nội bộ với họ . Như đã trình bày cho người dùng, một ảnh chụp nhanh chứa các tệp hoàn chỉnh, không chỉ khác biệt. Nhưng bên trong, vâng, Git sử dụng diffs để tạo ra các packfile lưu trữ các bản sửa đổi một cách hiệu quả. " (Điều này trái ngược hoàn toàn với, ví dụ: Subversion.)
user2864740

5
Git không theo dõi các tập tin, nó theo dõi changesets . Hầu hết các hệ thống kiểm soát phiên bản theo dõi các tập tin. Như một ví dụ về làm thế nào / tại sao điều này có thể quan trọng, hãy thử kiểm tra trong một thư mục trống để git (spolier: bạn không thể, bởi vì đó là một thay đổi "trống").
Elliott Frisch

12
@ElliottFrisch Điều đó không đúng. Mô tả của bạn gần với những gì ví dụ như darcs . Git lưu trữ ảnh chụp nhanh, không thay đổi.
melpomene

4
Tôi nghĩ rằng anh ta có nghĩa là Git không theo dõi một tập tin trực tiếp. Một tập tin bao gồm tên và nội dung của nó. Git theo dõi nội dung như đốm màu. Chỉ cung cấp một blob, bạn không thể biết tên tệp tương ứng của nó là gì. Nó có thể là nội dung của nhiều tệp có tên khác nhau dưới các đường dẫn khác nhau. Các ràng buộc giữa một tên đường dẫn và một đốm màu được mô tả trong một đối tượng cây.
ElpieKay

3
Liên quan: Randal Schwartz ' theo dõi bài nói chuyện của Linus (cũng là bài nói chuyện của Google Tech) - "... Git thực sự là gì về tất cả ... Linus đã nói Git là gì".
Peter Mortensen

Câu trả lời:


316

Trong CVS, lịch sử đã được theo dõi trên cơ sở mỗi tệp. Một nhánh có thể bao gồm nhiều tệp khác nhau với các phiên bản khác nhau, mỗi tệp có số phiên bản riêng. CVS được dựa trên RCS ( Hệ thống kiểm soát sửa đổi ), theo dõi các tệp riêng lẻ theo cách tương tự.

Mặt khác, Git chụp ảnh nhanh về trạng thái của toàn bộ dự án. Các tập tin không được theo dõi và phiên bản độc lập; một sửa đổi trong kho lưu trữ đề cập đến trạng thái của toàn bộ dự án, không phải là một tệp.

Khi Git đề cập đến việc theo dõi một tập tin, điều đó có nghĩa đơn giản là nó sẽ được đưa vào lịch sử của dự án. Cuộc nói chuyện của Linus không đề cập đến các tệp theo dõi trong ngữ cảnh Git, nhưng tương phản với mô hình CVS và RCS với mô hình dựa trên ảnh chụp nhanh được sử dụng trong Git.


4
Bạn có thể thêm rằng đây là lý do tại sao trong CVS và Subversion, bạn có thể sử dụng các thẻ như $Id$trong một tệp. Cùng không hoạt động trong git, vì thiết kế là khác nhau.
gerrit

58
Và nội dung không bị ràng buộc với một tập tin như bạn mong đợi. Hãy thử di chuyển 80% mã của một tệp này sang tệp khác. Git tự động phát hiện di chuyển tệp + thay đổi 20%, ngay cả khi bạn vừa di chuyển mã xung quanh trong các tệp hiện có.
allo

13
@allo Là một tác dụng phụ của điều đó, git có thể làm một việc mà những người khác không thể: khi hai tệp được hợp nhất và bạn sử dụng "git đổ lỗi -C", git có thể nhìn xuống cả hai lịch sử. Trong theo dõi dựa trên tệp, bạn phải chọn tệp gốc nào là tệp gốc và tất cả các dòng khác đều xuất hiện hoàn toàn mới.
Izkata

1
@allo, Izkata - Và đó là thực thể truy vấn giải quyết tất cả những điều này bằng cách phân tích nội dung repo tại thời điểm truy vấn (cam kết lịch sử và sự khác biệt giữa các cây và đốm tham chiếu), thay vì yêu cầu thực thể cam kết và người dùng của nó xác định hoặc tổng hợp chính xác thông tin này tại thời điểm cam kết - cũng không phải nhà phát triển công cụ repo để thiết kế & triển khai khả năng này và lược đồ siêu dữ liệu tương ứng trước khi công cụ được triển khai. Torvalds lập luận rằng phân tích như vậy sẽ chỉ trở nên tốt hơn theo thời gian, và tất cả lịch sử của mỗi repo git kể từ ngày đầu tiên sẽ có lợi.
Jeremy

1
@allo Yep, và để nhấn mạnh sự thật rằng git không hoạt động ở cấp độ tệp, bạn thậm chí không phải thực hiện tất cả các thay đổi trong một tệp; bạn có thể cam kết phạm vi dòng tùy ý trong khi để lại các thay đổi khác trong tệp bên ngoài cam kết. Tất nhiên giao diện người dùng cho điều đó gần như không đơn giản nên hầu hết không làm điều đó, nhưng nó hiếm khi có công dụng của nó.
Alvin Thompson

103

Tôi đồng ý với brian m. câu trả lời của carlson : Linus thực sự phân biệt, ít nhất là một phần, giữa các hệ thống kiểm soát phiên bản hướng tệp và cam kết. Nhưng tôi nghĩ có nhiều hơn thế.

Trong cuốn sách của tôi , bị đình trệ và có thể không bao giờ kết thúc, tôi đã cố gắng đưa ra một phân loại cho các hệ thống kiểm soát phiên bản. Trong phân loại học của tôi, thuật ngữ cho những gì chúng tôi quan tâm ở đây là tính nguyên tử của hệ thống kiểm soát phiên bản. Xem những gì hiện tại là trang 22. Khi một VCS có tính nguyên tử ở cấp độ tệp, trên thực tế có một lịch sử cho mỗi tệp. VCS phải nhớ tên của tệp và những gì đã xảy ra với nó tại mỗi điểm.

Git không làm điều đó. Git chỉ có một lịch sử cam kết, cam kết là đơn vị nguyên tử của nó và lịch sử tập hợp các xác nhận trong kho lưu trữ. Điều mà một cam kết ghi nhớ là dữ liệu. của cam kết cha mẹ của cam kết. (Chính cha mẹ này và biểu đồ chuyển hướng được định hướng được hình thành bằng cách đọc tất cả các cam kết và cha mẹ của họ, đó lịch sử trong kho lưu trữ.)

Lưu ý rằng một VCS có thể được định hướng theo cam kết, nhưng vẫn lưu trữ dữ liệu theo từng tệp. Đó là một chi tiết triển khai, mặc dù đôi khi là một chi tiết quan trọng và Git cũng không làm điều đó. Thay vào đó, mỗi cam kết ghi lại một cây , với các tên tệp , chế độ mã hóa đối tượng cây (nghĩa là tệp này có thực thi được hay không?) Và một con trỏ tới nội dung tệp thực tế . Nội dung được lưu trữ độc lập, trong một đối tượng blob . Giống như một đối tượng cam kết, một blob nhận được ID băm duy nhất cho nội dung của nó nhưng không giống như một cam kết, chỉ có thể xuất hiện một lần, blob có thể xuất hiện trong nhiều lần xác nhận. Vì vậy, nội dung tệp cơ bản trong Git được lưu trữ trực tiếp dưới dạng blob, và sau đó gián tiếp trong một đối tượng cây có ID băm được ghi lại (trực tiếp hoặc gián tiếp) trong đối tượng cam kết.

Khi bạn yêu cầu Git hiển thị cho bạn lịch sử của tệp bằng cách sử dụng:

git log [--follow] [starting-point] [--] path/to/file

những gì Git thực sự đang làm là đi theo lịch sử cam kết , đó là lịch sử duy nhất mà Git có, nhưng không hiển thị cho bạn bất kỳ cam kết nào trừ khi:

  • cam kết là một cam kết không hợp nhất và
  • cha mẹ của cam kết đó cũng có tệp, nhưng nội dung trong cha mẹ khác nhau hoặc cha mẹ của cam kết không có tệp nào cả

(nhưng một số trong những điều kiện có thể được sửa đổi thông qua thêm git logtùy chọn, và có một rất khó khăn để mô tả tác dụng phụ gọi là Lịch sử Đơn giản mà làm cho Git bỏ qua một số cam kết từ đi bộ lịch sử hoàn toàn). Lịch sử tệp bạn thấy ở đây không chính xác tồn tại trong kho lưu trữ, theo một nghĩa nào đó: thay vào đó, nó chỉ là một tập hợp con tổng hợp của lịch sử thực. Bạn sẽ nhận được một "lịch sử tập tin" khác nếu bạn sử dụng các git logtùy chọn khác nhau !


Một điều nữa để thêm vào là điều này cho phép Git làm những việc như nhân bản nông. Nó chỉ cần lấy lại cam kết đầu và tất cả các đốm màu mà nó đề cập đến. Nó không cần phải tạo lại các tập tin bằng cách áp dụng các bộ thay đổi.
Wes Toleman

@WesToleman: nó chắc chắn làm cho điều đó dễ dàng hơn. Cửa hàng Mercurial deltas, với các thiết lập lại thỉnh thoảng, và trong khi những người Mercurial có ý định thêm các bản sao nông ở đó (có thể là do ý tưởng "thiết lập lại"), họ thực sự chưa thực hiện được (vì đó là một thách thức kỹ thuật nhiều hơn).

@torek Tôi có nghi ngờ về mô tả của bạn về Git khi trả lời yêu cầu lịch sử tệp nhưng tôi nghĩ rằng nó xứng đáng với câu hỏi thích hợp của riêng mình: stackoverflow.com/questions/55616349/
Simón Ramírez Amaya

@torek Cảm ơn liên kết đến cuốn sách của bạn, tôi không thấy gì khác giống như vậy.
sởn gai ốc

17

Một chút khó hiểu là đây:

Git không bao giờ xem những cái đó là các tập tin cá nhân. Git nghĩ mọi thứ là nội dung đầy đủ.

Git thường sử dụng băm 160 bit thay cho các đối tượng trong repo của chính nó. Một cây các tệp về cơ bản là một danh sách các tên và giá trị băm liên quan đến nội dung của mỗi (cộng với một số siêu dữ liệu).

Nhưng hàm băm 160 bit xác định duy nhất nội dung (trong vũ trụ của cơ sở dữ liệu git). Vì vậy, một cây có băm như nội dung bao gồm nội dung ở trạng thái của nó.

Nếu bạn thay đổi trạng thái nội dung của tệp, hàm băm của nó sẽ thay đổi. Nhưng nếu hàm băm của nó thay đổi, hàm băm liên quan đến nội dung của tên tệp cũng thay đổi. Đến lượt nó thay đổi hàm băm của "cây thư mục".

Khi cơ sở dữ liệu git lưu trữ một cây thư mục, cây thư mục đó ngụ ý và bao gồm tất cả nội dung của tất cả các thư mục con và tất cả các tệp trong đó .

Nó được tổ chức theo cấu trúc cây với các con trỏ (bất biến, có thể tái sử dụng) cho các đốm màu hoặc các cây khác, nhưng về mặt logic, nó là một ảnh chụp nhanh toàn bộ nội dung của toàn bộ cây. Các đại diện trong cơ sở dữ liệu git không phải là nội dung dữ liệu phẳng, nhưng về mặt logic thì đó là tất cả dữ liệu của nó và không có gì khác.

Nếu bạn tuần tự hóa cây thành một hệ thống tập tin, đã xóa tất cả các thư mục .git và bảo git thêm cây vào cơ sở dữ liệu của nó, bạn sẽ không thêm gì vào cơ sở dữ liệu - phần tử sẽ có sẵn.

Nó có thể giúp nghĩ về băm của git như một con trỏ đếm tham chiếu đến dữ liệu bất biến.

Nếu bạn xây dựng một ứng dụng xung quanh đó, một tài liệu là một loạt các trang, có các lớp, có các nhóm, có các đối tượng.

Khi bạn muốn thay đổi một đối tượng, bạn phải tạo một nhóm hoàn toàn mới cho nó. Nếu bạn muốn thay đổi một nhóm, bạn phải tạo một lớp mới, cần một trang mới, cần một tài liệu mới.

Mỗi khi bạn thay đổi một đối tượng, nó sẽ sinh ra một tài liệu mới. Tài liệu cũ tiếp tục tồn tại. Tài liệu mới và cũ chia sẻ hầu hết nội dung của chúng - chúng có cùng trang (trừ 1). Một trang có các lớp giống nhau (trừ 1). Lớp đó có cùng các nhóm (trừ 1). Nhóm đó có cùng các đối tượng (trừ 1).

Và tương tự, tôi có nghĩa là một bản sao, nhưng thực hiện nó chỉ là một con trỏ đếm tham chiếu đến cùng một đối tượng bất biến.

Một repo git là rất nhiều như thế.

Điều này có nghĩa là một thay đổi git đã cho chứa thông điệp cam kết của nó (dưới dạng mã băm), nó chứa cây công việc của nó và nó chứa các thay đổi cha của nó.

Những thay đổi cha mẹ chứa những thay đổi cha mẹ của họ, tất cả các cách trở lại.

Một phần của repo git chứa lịch sử là chuỗi thay đổi. Chuỗi thay đổi đó ở cấp độ trên cây "thư mục" - từ cây "thư mục", bạn không thể duy nhất nhận được một bộ thay đổi và chuỗi thay đổi.

Để tìm hiểu điều gì xảy ra với một tệp, bạn bắt đầu với tệp đó trong tập thay đổi. Những thay đổi đó có một lịch sử. Thông thường trong lịch sử đó, cùng một tệp có tên tồn tại, đôi khi có cùng nội dung. Nếu nội dung giống nhau, không có thay đổi nào đối với tệp. Nếu nó khác, có một sự thay đổi, và công việc cần phải được thực hiện để tìm ra chính xác những gì.

Đôi khi các tập tin bị mất; nhưng, cây "thư mục" có thể có một tệp khác có cùng nội dung (cùng mã băm), vì vậy chúng tôi có thể theo dõi theo cách đó (lưu ý; đây là lý do tại sao bạn muốn một tệp cam kết di chuyển một tệp tách khỏi cam kết -biên tập). Hoặc cùng tên tệp và sau khi kiểm tra tệp là đủ tương tự.

Vì vậy, git có thể chắp vá một "lịch sử tập tin".

Nhưng lịch sử tệp này xuất phát từ việc phân tích hiệu quả "toàn bộ thay đổi", không phải từ một liên kết từ một phiên bản của tệp này sang phiên bản khác.


12

"Git không theo dõi tệp" về cơ bản có nghĩa là các cam kết của git bao gồm một ảnh chụp nhanh cây tệp kết nối một đường dẫn trong cây với một "blob" và một biểu đồ cam kết theo dõi lịch sử của các cam kết . Mọi thứ khác được xây dựng lại một cách nhanh chóng bằng các lệnh như "git log" và "git blame". Việc xây dựng lại này có thể được thông qua các tùy chọn khác nhau về mức độ khó để tìm kiếm các thay đổi dựa trên tệp. Các heuristic mặc định có thể xác định khi một blob thay đổi vị trí trong cây tệp mà không thay đổi hoặc khi một tệp được liên kết với một blob khác so với trước đây. Các cơ chế nén mà Git sử dụng không quan tâm nhiều đến ranh giới blob / file. Nếu nội dung đã ở đâu đó, điều này sẽ giữ cho sự phát triển của kho lưu trữ nhỏ mà không liên kết các đốm màu khác nhau.

Bây giờ đó là kho lưu trữ. Git cũng có một cây làm việc, và trong cây làm việc này có các tệp được theo dõi và không bị theo dõi. Chỉ các tệp được theo dõi được ghi lại trong chỉ mục (khu vực tổ chức? Bộ đệm?) Và chỉ những gì được theo dõi ở đó mới đưa nó vào kho lưu trữ.

Chỉ mục là hướng tệp và có một số lệnh hướng tệp để thao tác với nó. Nhưng những gì kết thúc trong kho lưu trữ chỉ là các cam kết ở dạng ảnh chụp nhanh của cây tệp và dữ liệu blob liên quan và tổ tiên của cam kết.

Vì Git không theo dõi lịch sử tập tin và đổi tên và hiệu quả của nó không phụ thuộc vào chúng, đôi khi bạn phải thử một vài lần với các tùy chọn khác nhau cho đến khi Git tạo ra lịch sử / diffs / đổ lỗi cho bạn về lịch sử không tầm thường.

Điều đó khác với các hệ thống như Subversion ghi lại thay vì xây dựng lại lịch sử. Nếu nó không được ghi lại, bạn không được nghe về nó.

Tôi thực sự đã xây dựng một trình cài đặt khác biệt tại một thời điểm chỉ so sánh các cây phát hành bằng cách kiểm tra chúng vào Git và sau đó tạo ra một kịch bản nhân đôi hiệu ứng của chúng. Vì đôi khi toàn bộ cây được di chuyển, điều này tạo ra các trình cài đặt vi sai nhỏ hơn nhiều so với ghi đè / xóa mọi thứ sẽ tạo ra.


7

Git không theo dõi tệp trực tiếp, nhưng theo dõi ảnh chụp nhanh của kho lưu trữ và những ảnh chụp nhanh này xảy ra bao gồm các tệp.

Đây là một cách để xem xét nó.

Trong các hệ thống kiểm soát phiên bản khác (SVN, Rational ClearCase), bạn có thể nhấp chuột phải vào một tệp và nhận lịch sử thay đổi của nó .

Trong Git, không có lệnh trực tiếp nào thực hiện điều này. Xem câu hỏi này . Bạn sẽ ngạc nhiên về số lượng câu trả lời khác nhau. Không có câu trả lời đơn giản nào vì Git không chỉ đơn giản là theo dõi một tệp , không phải theo cách mà SVN hoặc ClearCase thực hiện.


5
Tôi nghĩ rằng tôi hiểu những gì bạn đang cố nói, nhưng "Trong Git, không có lệnh trực tiếp nào thực hiện điều này" bị mâu thuẫn trực tiếp bởi các câu trả lời cho câu hỏi bạn đã liên kết. Mặc dù sự thật là phiên bản xảy ra ở cấp độ của toàn bộ kho lưu trữ, nhưng thường có rất nhiều cách để đạt được bất cứ điều gì trong Git, do đó, có nhiều lệnh để hiển thị lịch sử của tệp không phải là bằng chứng nhiều.
Joe Lee-Moyet

Tôi đã đọc lướt qua vài câu trả lời đầu tiên của câu hỏi mà bạn đã liên kết và tất cả chúng đều sử dụng git loghoặc một số chương trình được xây dựng trên đó (hoặc một số bí danh thực hiện điều tương tự). Nhưng ngay cả khi có nhiều cách khác nhau, như Joe nói điều đó cũng đúng khi hiển thị lịch sử chi nhánh. (cũng git log -p <file>được xây dựng và thực hiện chính xác điều đó)
Voo

Bạn có chắc chắn rằng SVN lưu trữ nội bộ các thay đổi trên mỗi tệp không? Tôi đã không sử dụng nó trong một thời gian, nhưng tôi mơ hồ nhớ rằng có các tệp có tên như id phiên bản, thay vì phản ánh cấu trúc tệp dự án.
Artur Biesiadowski

3

Theo dõi "nội dung", tình cờ, là những gì dẫn đến không theo dõi các thư mục trống.
Đó là lý do tại sao, nếu bạn git rm tệp cuối cùng của một thư mục, chính thư mục đó sẽ bị xóa .

Điều đó không phải luôn luôn như vậy và chỉ Git 1.4 (tháng 5 năm 2006) thi hành chính sách "theo dõi nội dung" với cam kết 443f833 :

trạng thái git: bỏ qua các thư mục trống và thêm -u để hiển thị tất cả các tệp không bị theo dõi

Theo mặc định, chúng tôi sử dụng --others --directoryđể hiển thị các thư mục không thú vị (để thu hút sự chú ý của người dùng) mà không có nội dung của chúng (để đầu ra không rõ ràng).
Hiển thị các thư mục trống không có ý nghĩa, vì vậy hãy vượt qua --no-empty-directorykhi chúng ta làm như vậy.

Đưa ra -u(hoặc --untracked) vô hiệu hóa việc không lộn xộn này để cho phép người dùng nhận được tất cả các tệp không bị theo dõi.

Điều đó đã được lặp lại nhiều năm sau đó vào tháng 1 năm 2011 với cam kết 8fe533 , Git v1.7.4:

Điều này phù hợp với triết lý UI chung: git theo dõi nội dung, không phải các thư mục trống.

Trong khi đó, với Git 1.4.3 (tháng 9 năm 2006), Git bắt đầu giới hạn nội dung không bị theo dõi đối với các thư mục không trống, với cam kết 2074cb0 :

không nên liệt kê nội dung của các thư mục hoàn toàn không bị theo dõi, mà chỉ liệt kê tên của thư mục đó (cộng với dấu ' /').

Nội dung theo dõi là những gì cho phép git đổ lỗi, từ rất sớm (Git 1.4.4, tháng 10 năm 2006, cam kết cee7f24 ) sẽ hiệu quả hơn:

Quan trọng hơn, cấu trúc bên trong của nó được thiết kế để hỗ trợ chuyển động nội dung (còn gọi là cắt và dán) dễ dàng hơn bằng cách cho phép nhiều hơn một đường dẫn được thực hiện từ cùng một cam kết.

Đó (nội dung theo dõi) cũng là thứ đưa git thêm vào API Git, với Git 1.5.0 (tháng 12 năm 2006, cam kết 366bfcb )

làm cho 'git add' một giao diện thân thiện với người dùng hạng nhất vào chỉ mục

Điều này mang lại sức mạnh của chỉ số lên phía trước bằng cách sử dụng một mô hình tinh thần phù hợp mà không nói về chỉ số nào cả.
Xem ví dụ như làm thế nào tất cả các cuộc thảo luận kỹ thuật đã được sơ tán khỏi trang man git-add.

Bất kỳ nội dung được cam kết phải được thêm vào với nhau.
Cho dù nội dung đó đến từ các tệp mới hoặc các tệp sửa đổi không thành vấn đề.
Bạn chỉ cần "thêm" nó, bằng git-add hoặc bằng cách cung cấp git-commit với -a(tất nhiên đối với các tệp đã biết).

Đó là những gì git add --interactivecó thể, với cùng một Git 1.5.0 ( cam kết 5cde71d )

Sau khi thực hiện lựa chọn, hãy trả lời bằng một dòng trống để tạo nội dung của các tệp cây làm việc cho các đường dẫn được chọn trong chỉ mục.

Đó cũng là lý do tại sao, để loại bỏ đệ quy tất cả nội dung khỏi một thư mục, bạn cần phải vượt qua -rtùy chọn, không chỉ tên thư mục là <path>(vẫn là Git 1.5.0, cam kết 9f95069 ).

Xem nội dung tệp thay vì chính tệp là những gì cho phép kịch bản hợp nhất giống như kịch bản được mô tả trong cam kết 1de70db (Git v2.18.0-rc0, tháng 4 năm 2018)

Xem xét việc hợp nhất sau với đổi tên / thêm xung đột:

  • bên A: sửa đổi foo, thêm không liên quanbar
  • bên B: đổi tên foo->bar(nhưng không sửa đổi chế độ hoặc nội dung)

Trong trường hợp này, việc hợp nhất ba chiều của foo gốc, foo của A và B barsẽ dẫn đến một tên đường dẫn mong muốn barcó cùng chế độ / nội dung mà A có foo.
Do đó, A có chế độ và nội dung phù hợp cho tệp và nó có tên đường dẫn đúng (cụ thể là bar).

Cam kết 37b65ce , Git v2.21.0-rc0, tháng 12 năm 2018, gần đây đã cải thiện các giải pháp xung đột va chạm.
cam kết bbafc9c Firther minh họa tầm quan trọng của việc xem xét nội dung tệp , bằng cách cải thiện việc xử lý các xung đột đổi tên / đổi tên (2to1):

  • Thay vì lưu trữ tệp tại collide_path~HEADcollide_path~MERGE, các tệp được hợp nhất và ghi lại hai chiều tại collide_path.
  • Thay vì ghi phiên bản của tệp được đổi tên tồn tại ở phía được đổi tên trong chỉ mục (do đó bỏ qua mọi thay đổi được thực hiện cho tệp ở phía lịch sử mà không đổi tên), chúng tôi thực hiện hợp nhất nội dung ba chiều trên tên được đổi tên đường dẫn, sau đó lưu trữ ở giai đoạn 2 hoặc giai đoạn 3.
  • Lưu ý rằng vì hợp nhất nội dung cho mỗi lần đổi tên có thể có xung đột và sau đó chúng tôi phải hợp nhất hai tệp được đổi tên, chúng tôi có thể kết thúc bằng các dấu xung đột lồng nhau.
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.