Cập nhật mô hình con Git


242

Tôi không rõ ý nghĩa của những điều sau đây (từ tài liệu cập nhật mô hình con Git ):

... sẽ làm cho các mô đun con ĐẦU bị tách ra, trừ khi --rebasehoặc --mergeđược chỉ định ...

Làm thế nào --rebase/ --mergethay đổi mọi thứ?

Trường hợp sử dụng chính của tôi là có một loạt các kho lưu trữ trung tâm, mà tôi sẽ nhúng qua các mô hình con vào các kho lưu trữ khác. Tôi muốn có thể cải thiện các kho lưu trữ trung tâm này, trực tiếp ở vị trí ban đầu của chúng hoặc từ trong kho nhúng của chúng (những kho sử dụng chúng thông qua mô hình con).

  • Từ bên trong các mô hình con này, tôi có thể tạo các nhánh / sửa đổi và sử dụng đẩy / kéo giống như tôi làm trong các kho lưu trữ thông thường, hoặc có những điều cần thận trọng không?
  • Làm cách nào để tôi tiến hành cam kết tham chiếu mô hình con từ say (được gắn thẻ) 1.0 đến 1.1 (mặc dù phần đầu của kho lưu trữ ban đầu đã ở mức 2.0) hoặc chọn tất cả các cam kết của chi nhánh được sử dụng?

Về chủ đề "tách đầu", xem thêm stackoverflow.com/questions/964876/head-and-orighead-in-gitstackoverflow.com/questions/237408/ cho một ví dụ thực tế (không liên quan đến mô hình con, nhưng vẫn )
VonC

"Bạn không thể sửa đổi nội dung của mô hình con từ bên trong dự án chính": có, đúng. Và tôi đã chỉnh sửa câu trả lời của mình để làm sáng tỏ mâu thuẫn rõ ràng đó (mô hình con không thể sửa đổi, mà bạn vẫn có thể sửa đổi từ repo dự án chính!)
VonC

Câu trả lời:


304

Đây trang GitPro không tóm tắt các kết quả của một bản cập nhật git submodule độc đáo

Khi bạn chạy git submodule update, nó sẽ kiểm tra phiên bản cụ thể của dự án, nhưng không nằm trong một nhánh. Điều này được gọi là có một đầu tách ra - nó có nghĩa là tệp CHÍNH chỉ trực tiếp đến một cam kết, không phải là một tham chiếu tượng trưng.
Vấn đề là bạn thường không muốn làm việc trong môi trường tách rời, bởi vì điều đó dễ làm mất các thay đổi .
Nếu bạn thực hiện cập nhật mô hình con ban đầu, hãy cam kết trong thư mục mô hình con đó mà không tạo một nhánh để làm việc và sau đó chạy lại cập nhật mô hình con git từ siêu dự án mà không cam kết, Git sẽ ghi đè lên các thay đổi của bạn mà không cho bạn biết. Về mặt kỹ thuật, bạn sẽ không mất công, nhưng bạn sẽ không có chi nhánh chỉ vào nó, do đó sẽ hơi khó lấy.


Lưu ý tháng 3 năm 2013:

Như đã đề cập trong " theo dõi mô hình con git mới nhất ", một mô hình con bây giờ (git1.8.2) có thể theo dõi một nhánh.

# add submodule to track master branch
git submodule add -b master [URL to Git repo];

# update your submodule
git submodule update --remote 
# or (with rebase)
git submodule update --rebase --remote

Xem " git submodule update --remoteso vớigit pull ".

Câu trả lời của MindTooth minh họa một bản cập nhật thủ công (không có cấu hình cục bộ):

git submodule -q foreach git pull -q origin master

Trong cả hai trường hợp, điều đó sẽ thay đổi các tham chiếu mô đun con ( gitlink , một mục đặc biệt trong chỉ mục repo cha ) và bạn sẽ cần thêm, cam kết và đẩy các tham chiếu đã nói từ repo chính.
Lần tới, bạn sẽ sao chép repo cha đó, nó sẽ điền vào các mô hình con để phản ánh các tham chiếu SHA1 mới đó.

Phần còn lại của câu trả lời này mô tả chi tiết tính năng mô hình con cổ điển (tham chiếu đến một cam kết cố định , đó là tất cả các điểm đằng sau khái niệm của một mô hình con).


Để tránh vấn đề này, hãy tạo một nhánh khi bạn làm việc trong một thư mục mô hình con với công việc kiểm tra git -b hoặc một cái gì đó tương đương. Khi bạn thực hiện cập nhật mô hình con lần thứ hai, nó vẫn sẽ hoàn nguyên công việc của bạn, nhưng ít nhất bạn có một con trỏ để quay lại.

Chuyển đổi các nhánh với mô đun con trong chúng cũng có thể là khó khăn. Nếu bạn tạo một nhánh mới, thêm một mô hình con ở đó, và sau đó chuyển trở lại một nhánh mà không có mô hình con đó, bạn vẫn có thư mục mô hình con như một thư mục chưa được theo dõi:


Vì vậy, để trả lời câu hỏi của bạn:

Tôi có thể tạo các nhánh / sửa đổi và sử dụng đẩy / kéo giống như trong các repos thông thường không, hoặc có những điều cần thận trọng không?

Bạn có thể tạo một nhánh và sửa đổi đẩy.

CẢNH BÁO (từ Hướng dẫn mô hình con Git ): Luôn xuất bản (đẩy) thay đổi mô hình con trước khi xuất bản (đẩy) thay đổi thành siêu dự án tham chiếu đến nó. Nếu bạn quên xuất bản thay đổi mô hình con, những người khác sẽ không thể sao chép kho lưu trữ.

Làm thế nào tôi có thể nâng cấp cam kết tham chiếu mô hình con từ say (được gắn thẻ) 1.0 lên 1.1 (mặc dù phần đầu của repo gốc đã ở mức 2.0)

Trang " Hiểu các mô hình con " có thể giúp

Các mô đun con Git được thực hiện bằng hai phần chuyển động:

  • các .gitmodulestập tin và
  • một loại đối tượng cây đặc biệt.

Chúng cùng nhau sắp xếp một bản sửa đổi cụ thể của một kho lưu trữ cụ thể được kiểm tra vào một vị trí cụ thể trong dự án của bạn.


Từ trang tiểu trình git

bạn không thể sửa đổi nội dung của mô hình con từ trong dự án chính

Chính xác 100%: bạn không thể sửa đổi một mô hình con, chỉ tham khảo một trong các cam kết của nó.

Đây là lý do tại sao, khi bạn sửa đổi một mô hình con từ trong dự án chính, bạn:

  • cần phải cam kết và đẩy trong mô hình con (đến mô đun ngược dòng) và
  • sau đó đi lên trong dự án chính của bạn và tái cam kết (để dự án chính đó tham chiếu đến mô hình con mới mà bạn vừa tạo và đẩy)

Một mô hình con cho phép bạn có một sự phát triển tiếp cận dựa trên thành phần , trong đó dự án chính chỉ đề cập đến các cam kết cụ thể của các thành phần khác (ở đây "các kho Git khác được khai báo là các mô đun con").

Một mô hình con là một điểm đánh dấu (cam kết) với kho lưu trữ Git khác không bị ràng buộc bởi chu trình phát triển dự án chính: nó (repo Git "khác" có thể phát triển độc lập.
Tùy thuộc vào dự án chính để chọn từ repo khác đó bất cứ cam kết nào nó cần.

Tuy nhiên, nếu bạn muốn, để thuận tiện , hãy sửa đổi một trong những mô hình con đó trực tiếp từ dự án chính của bạn, Git cho phép bạn làm điều đó, với điều kiện trước tiên bạn phải xuất bản những sửa đổi mô hình con đó cho repo Git ban đầu của nó, sau đó cam kết tham chiếu dự án chính của bạn một phiên bản mới của mô hình con nói.

Nhưng ý tưởng chính vẫn là: tham khảo các thành phần cụ thể trong đó:

  • có vòng đời của riêng họ
  • có bộ thẻ riêng
  • có sự phát triển của riêng họ

Danh sách các cam kết cụ thể mà bạn đang tham khảo trong dự án chính xác định cấu hình của bạn (đây là tất cả những gì về Quản lý cấu hình , bao gồm cả Hệ thống kiểm soát phiên bản đơn thuần )

Nếu một thành phần thực sự có thể được phát triển cùng lúc với dự án chính của bạn (bởi vì bất kỳ sửa đổi nào trong dự án chính sẽ liên quan đến sửa đổi thư mục con và ngược lại), thì đó sẽ không phải là "mô hình con", mà là một hợp nhất cây con (cũng được trình bày trong câu hỏi Chuyển cơ sở mã kế thừa từ cvs sang kho lưu trữ phân tán ), liên kết lịch sử của hai repo Git với nhau.

Điều đó có giúp hiểu bản chất thực sự của Submodules Git không?


77
Ồ Đó là một lời giải thích dài cho một cái gì đó chủ yếu là đơn giản nên đủ để khiến bất kỳ người mới nào sợ hãi chỉ cần gắn bó với svn: externals của họ. ;-)
Conny

2
@conny: nhưng, như tôi mô tả chi tiết trong " Tại sao các mô đun con git không tương thích với các bên ngoài svn? ", các mô hình con là cơ bản khác nhau và không tương thích với svn:externals.
VonC

1
Xin lỗi, để trả lời câu hỏi của riêng tôi, tôi tập hợp cd'ing vào mô hình con và kiểm tra git một sha, hoặc git pull / fetch sẽ làm tốt. Sau đó cam kết cập nhật trong kho lưu trữ cục bộ.
Henrik

2
@hced: Bạn cũng có thể nhấn tất cả các mô hình con cùng một lúc bằng cách sử dụnggit submodule foreach
Dav Clark

1
.. vẫn không nhận được nó. Có một lời giải thích dễ dàng hơn trên web ở đâu đó?
eugene

135

Để cập nhật từng mô hình con, bạn có thể gọi lệnh sau (tại thư mục gốc của kho lưu trữ):

git submodule -q foreach git pull -q origin master

Bạn có thể loại bỏ tùy chọn -q để theo toàn bộ quá trình.


15
Nếu bạn chỉ chạy git submodule update --init --recursivetừ gốc, nó sẽ nhận được tất cả chúng một cách đệ quy và khởi tạo chúng nếu chúng chưa có.
Sam Soffes

10
@SamSoffes Điều đó phục vụ một mục đích hoàn toàn khác. Cập nhật các mô hình con sẽ kiểm tra các mô hình con tại cam kết mà chúng hiện đang trỏ tới (không nhất thiết là cam kết mới nhất). Giải pháp trong câu trả lời ở trên cập nhật cam kết của từng mô hình con lên TRƯỚC mới nhất từ ​​nguồn gốc / chủ.
indragie

7
Phương pháp mới của tôi:git submodule update --rebase --remote
MindTooth

19

Để giải quyết tùy chọn --rebasevs.--merge

Giả sử bạn có siêu kho A và mô đun con B và muốn thực hiện một số công việc trong mô hình con B. Bạn đã hoàn thành bài tập về nhà và biết rằng sau khi gọi

git submodule update

bạn đang ở trạng thái KHÔNG CÓ ĐẦU, do đó, bất kỳ cam kết nào bạn thực hiện tại thời điểm này đều khó có thể quay lại. Vì vậy, bạn đã bắt đầu làm việc trên một nhánh mới trong mô hình con B

cd B
git checkout -b bestIdeaForBEver
<do work>

Trong khi đó, một người khác trong dự án A đã quyết định rằng phiên bản B mới nhất và lớn nhất thực sự là những gì A xứng đáng. Bạn, theo thói quen, hợp nhất các thay đổi gần đây nhất và cập nhật các mô hình con của bạn.

<in A>
git merge develop
git submodule update

Ôi không! Bạn đang trở lại trạng thái không đầu một lần nữa, có lẽ vì B hiện đang chỉ vào SHA được liên kết với mẹo mới của B hoặc một số cam kết khác. Giá như bạn có:

git merge develop
git submodule update --rebase

Fast-forwarded bestIdeaForBEver to b798edfdsf1191f8b140ea325685c4da19a9d437.
Submodule path 'B': rebased into 'b798ecsdf71191f8b140ea325685c4da19a9d437'

Bây giờ, ý tưởng tốt nhất từ ​​trước đến nay đối với B đã được phản đối vào cam kết mới, và quan trọng hơn, bạn vẫn đang ở trong nhánh phát triển của mình cho B, không phải trong trạng thái không đầu!

( --mergeSẽ hợp nhất các thay đổi từ beforeUpdateSHA sang afterUpdateSHA vào nhánh làm việc của bạn, trái ngược với việc từ chối các thay đổi của bạn lên afterUpdateSHA.)


7

Git 1.8.2 có một tùy chọn mới --remote, sẽ cho phép chính xác hành vi này. Đang chạy

git submodule update --rebase --remote

sẽ lấy các thay đổi mới nhất từ ​​thượng nguồn trong mỗi mô hình con, khởi động lại chúng và kiểm tra phiên bản mới nhất của mô hình con. Như tài liệu đưa ra:

--Xa xôi

Tùy chọn này chỉ hợp lệ cho lệnh cập nhật. Thay vì sử dụng SHA-1 được ghi lại của siêu dự án để cập nhật mô hình con, hãy sử dụng trạng thái của nhánh theo dõi từ xa của mô hình con.

Điều này tương đương với việc chạy git pulltrong mỗi mô hình con, thường là chính xác những gì bạn muốn.

(Điều này đã được sao chép từ câu trả lời này .)


Nếu bạn quyết định trả lời một câu hỏi cũ hơn và có câu trả lời đúng, việc thêm câu trả lời mới vào cuối ngày có thể không giúp bạn nhận được bất kỳ tín dụng nào. Nếu bạn có một số thông tin mới đặc biệt hoặc bạn tin chắc rằng các câu trả lời khác đều sai, bằng mọi cách hãy thêm một câu trả lời mới, nhưng 'một câu trả lời khác' đưa ra thông tin cơ bản tương tự trong một thời gian dài sau khi câu hỏi được hỏi thường thắng ' t kiếm được cho bạn nhiều tín dụng. Không có lời giải thích về những gì nó làm - thậm chí không có liên kết đến tài liệu bên ngoài (sẽ không đủ).
Jonathan Leffler

2
Đó không phải là "câu trả lời khác", vì KHÔNG có câu trả lời nào khác có lệnh này (chứng minh tôi sai). Các câu trả lời khác không hiệu quả với tôi, nhận xét này đã có, vì vậy tôi quyết định đăng nó dưới dạng câu trả lời trong khi cung cấp tín dụng cho chủ sở hữu ban đầu. Vì vậy, hãy xem xét loại bỏ downvote của bạn.
Iulian Onofrei

Có một bình luận của MindTooth từ năm 2015 nói rằng đây là những gì họ làm bây giờ. Bạn không đưa ra lời giải thích nào về việc này (mặc dù bạn có đề cập đến MindTooth, nhưng không có lời giải thích thực sự nào về ý nghĩa của bạn - việc nhúng URL, như trong nhận xét này, sẽ giúp ích). Bạn không nói tại sao nó là một ý tưởng tốt. Bạn không đưa ra bất kỳ cảnh báo. Theo quan điểm của tôi, đây không phải là một câu trả lời hữu ích vì nó đặt ra nhiều câu hỏi hơn là giải quyết.
Jonathan Leffler

1
Điều đó có nghĩa là nó hoạt động thay vì không hoạt động. Tin tôi đi, nếu có nhiều người nhìn thấy câu trả lời này, họ sẽ rất vui, vì nó hiệu quả . Đối với những thứ như thế này, hầu hết mọi người chỉ muốn biết lệnh cập nhật một mô hình con git, chứ không phải cách nó được thực hiện.
Iulian Onofrei

Tôi đã chỉnh sửa câu trả lời để chứng minh bạn sai, đồng thời, stackoverflow.com/questions/1979167/git-submodule-update/ , !!!
Iulian Onofrei
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.