Bỏ qua các cam kết mới cho mô-đun con git


82

Lý lịch

Sử dụng Git 1.8.1.1 trên Linux. Kho lưu trữ trông như sau:

master
  book

Mô-đun con được tạo như sau:

$ cd /path/to/master
$ git submodule add https://user@bitbucket.org/user/repo.git book

book-đun con là sạch:

$ cd /path/to/master/book/
$ git status
# On branch master
nothing to commit, working directory clean

Vấn đề

Mặt khác, tổng thể cho thấy có "cam kết mới" cho mô-đun con của cuốn sách:

$ cd /path/to/master/
$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   book (new commits)
#
no changes added to commit (use "git add" and/or "git commit -a")

Git nên bỏ qua hoàn toàn thư mục mô-đun con, để cái chính cũng sạch:

$ cd /path/to/master/
$ git status
# On branch master
nothing to commit, working directory clean

Không cố gắng # 1 - bẩn

Bên trong tệp master/.gitmoduleslà như sau, theo câu trả lời này :

[submodule "book"]
        path = book
        url = https://user@bitbucket.org/user/repo.git
        ignore = dirty

Không cố gắng # 2 - không được theo dõi

Đã thay đổi master/.gitmodulesthành như sau, theo câu trả lời này :

[submodule "book"]
        path = book
        url = https://user@bitbucket.org/user/repo.git
        ignore = untracked

Không thử được # 3 - showUntrackedFiles

Đã chỉnh sửa master/.git/configphần sau, theo câu trả lời này :

[status]
   showUntrackedFiles = no

Nỗ lực thất bại # 4 - bỏ qua

Đã thêm thư mục sách vào tệp bỏ qua chính:

$ cd /path/to/master/
$ echo book > .gitignore

Không thành công # 5 - sao chép

Đã thêm thư mục sách vào trang cái như sau:

$ cd /path/to/master/
$ rm -rf book
$ git clone https://user@bitbucket.org/user/repo.git book

Câu hỏi

Làm thế nào để bookmô-đun con có thể nằm trong thư mục kho lưu trữ của chính nó trong masterkho lưu trữ mà git bỏ qua bookmô-đun con? Đó là, những điều sau sẽ không hiển thị:

#
#       modified:   book (new commits)
#

Làm thế nào để ngăn chặn thông báo đó khi thực thi git statustrong kho lưu trữ chính?

Một bài báo về cạm bẫy git submodule cho thấy đây là một cách sử dụng submodule không phù hợp?


3
Bạn thường sử dụng mô-đun con nếu bạn muốn liên kết kho lưu trữ với một phiên bản nhất định của kho lưu trữ khác và theo dõi điều đó. Nhưng điều đó dường như không phải là điều bạn muốn. Bạn chỉ muốn sử dụng một kho lưu trữ bên trong một kho lưu trữ khác mà không cần theo dõi nó. Sau đó, đừng thêm nó làm mô-đun con.
Felix Kling,

@FelixKling, nếu bạn thêm các repo như vậy và đẩy nó lên GitHub, liệu nó có chỉ tạo liên kết cho nó mà không sao chép nội dung của các thư mục đó không?
Roman Bekkiev

@Roland: Mô-đun con chỉ là các tệp có tham chiếu đến phiên bản của một kho lưu trữ khác. Khi chúng được khởi tạo trong bản sao cục bộ của kho lưu trữ, chúng sẽ được thay thế bằng nội dung thực của kho lưu trữ.
Felix Kling

2
Tôi nghĩ rằng bạn đang tìm kiếm "bỏ qua = tất cả"
greuze

1
Với Git 2.13 (Quý 2 năm 2017), bạn sẽ có thể xem xét git config submodule.<name>.active false. Xem câu trả lời của tôi bên dưới
VonC

Câu trả lời:


59

Để bao gồm một kho lưu trữ khác, không cần theo dõi trong siêu kho lưu trữ của nó, hãy thử cách này:

$ cd /path/to/master/
$ rm -rf book
$ git clone https://user@bitbucket.org/user/repo.git book
$ git add book
$ echo "book" >> .gitignore

Sau đó cam kết.

Như đã nêu trong bài viết cạm bẫy git con được liên kết :

... mối liên kết duy nhất giữa mô-đun mẹ và mô-đun con là [giá trị] được ghi lại của SHA đã kiểm tra của mô-đun con được lưu trữ trong các cam kết của mô-đun mẹ.

Điều đó có nghĩa là một mô-đun con không được lưu bởi nhánh hoặc thẻ đã đăng xuất của nó, mà luôn được lưu bởi một cam kết cụ thể; commit đó (SHA) được lưu vào super-repo (cái chứa submodule) giống như một tệp văn bản bình thường (tất nhiên, nó được đánh dấu là một tham chiếu).

Khi bạn kiểm tra một cam kết khác trong mô-đun con hoặc thực hiện một cam kết mới trong đó, super-repo sẽ thấy rằng SHA đã kiểm tra của nó đã thay đổi. Đó là khi bạn nhận được modified (new commits)dòng từ git status.

Để loại bỏ điều đó, bạn có thể:

  • git submodule update, Mà sẽ thiết lập lại submodule đến các cam kết hiện lưu trong các siêu repo (để biết chi tiết thấy các git submodulemanpage ; hoặc
  • git add book && git commit để lưu SHA mới vào super-repo.

Như đã đề cập trong phần nhận xét, hãy cân nhắc việc bỏ bookmô-đun con: sao chép nó bên trong super-repo, nếu việc theo dõi trạng thái của nó như một phần của super-repo là không cần thiết.


3
Ồ, giờ thì tôi đã hiểu, tại sao siêu mô-đun cần biết phiên bản của mô-đun con. Tất nhiên, nó có ý nghĩa để làm git add book && git commit. Tôi không nhận ra rằng git thực sự có thể đảm bảo rằng hai repo được đồng bộ hóa.
Sergey Orshanskiy

101

Chỉ cần chạy:

$ git submodule update

Thao tác này sẽ hoàn nguyên mô-đun con về cam kết cũ (được chỉ định trong repo gốc), mà không cập nhật repo mẹ với phiên bản mới nhất của mô-đun con.


6
Không, không, nó sẽ không thay đổi trạng thái.
Ed Bishop

Tại sao chính xác OP muốn không có mới nhất từ bookkho lưu trữ? Tôi không nghĩ câu trả lời của bạn có ý nghĩa gì trong bối cảnh này.
Alexis Wilke

@AlexisWilke và nếu giao diện sách thay đổi đáng kể và OP không có thời gian để thực hiện thay đổi trong bản tổng thể?
Logman

Đây là câu trả lời mà tôi đang tìm kiếm!
LLSv2.0

21

Có hai loại thông báo thay đổi mà bạn có thể chặn (từ git 1.7.2).

Đầu tiên là nội dung không được theo dõi xảy ra khi bạn thực hiện các thay đổi đối với mô-đun con của mình nhưng chưa thực hiện các thay đổi đó. Kho lưu trữ mẹ thông báo những điều này và trạng thái git báo cáo nó tương ứng:

modified: book (untracked content)

Bạn có thể ngăn chặn những điều này bằng:

[submodule "book"]
    path = modules/media
    url = https://user@bitbucket.org/user/repo.git
    ignore = dirty

Tuy nhiên, khi bạn thực hiện những thay đổi đó, kho lưu trữ mẹ sẽ một lần nữa lưu ý và báo cáo chúng một cách phù hợp:

modified:   book (new commits)

Nếu bạn cũng muốn ngăn chặn những điều này, bạn cần phải bỏ qua tất cả các thay đổi

[submodule "book"]
    path = book
    url = https://user@bitbucket.org/user/repo.git
    ignore = all

Hãy tưởng tượng tôi đã thêm ignore = alltùy chọn vào tất cả các mô-đun con. Cuối cùng một số mô-đun có cam kết mới đã được đẩy. Nếu ai đó sau đó sao chép super-repo, nó sẽ ở trạng thái cũ của mô-đun con hay nó sẽ kiểm tra những mô-đun mới nhất?
FelikZ

Với lệnh, git clone --recursive git@...bạn sẽ nhận được trạng thái cũ của các mô-đun con. Để cập nhật chúng, bạn sẽ cần một cái gì đó giống như git submodule foreach "git pull"sau khi nhân bản
greuze

1
Thật không may, ignore = alltùy chọn không bỏ qua các cam kết mới của mô-đun con. Tôi đang chạy phiên bản git 1.7.1. Bất kỳ ý tưởng cách nào?
Romulus

10

Git 2.13 (Quý 2 năm 2017) sẽ thêm một cách khác để bao gồm một mô-đun con không cần được theo dõi bởi repo mẹ của nó.

Trong trường hợp của OP:

git config submodule.<name>.active false

Xem cam kết 1b614c0 , cam kết 1f8d711 , cam kết bb62e0a , cam kết 3e7eaed , cam kết a086f92 ( 17/03/2017 ) và cam kết ee92ab9 , cam kết 25b31f1 , cam kết e7849a9 , cam kết 6dc9f01 , cam kết 5c2bd8b (16/03/2017) bởi Brandon Williams ( mbrandonw) .
(Hợp nhất bởi Junio ​​C Hamano - gitster- in cam kết a93dcb0 , ngày 30 tháng 3 năm 2017)

submodule: url tách và sở thích mô-đun con

Hiện tại, submodule.<name>.urltùy chọn cấu hình được sử dụng để xác định xem một mô-đun con nhất định có được người dùng quan tâm hay không. Điều này kết thúc là cồng kềnh trong một thế giới mà chúng ta muốn kiểm tra các mô-đun con khác nhau trong các chế độ làm việc khác nhau hoặc một cơ chế tổng quát hơn để chọn mô-đun con nào được quan tâm.

Trong tương lai với sự hỗ trợ của worktree cho các mô-đun con, sẽ có nhiều cây làm việc, mỗi cây có thể chỉ cần một tập hợp con của các mô-đun con được kiểm tra.
URL (là nơi có thể lấy kho mô-đun con) không được khác nhau giữa các cây làm việc khác nhau.

Nó cũng có thể thuận tiện cho người dùng khi chỉ định dễ dàng hơn các nhóm mô-đun con mà họ quan tâm thay vì đang chạy "git submodule init <path> " trên mỗi mô-đun con mà họ muốn kiểm tra trong cây làm việc của họ.

Cuối cùng, hai tùy chọn cấu hình được giới thiệu, submodule.activesubmodule.<name>.active.

  • Các submodule.activecấu hình giữ một pathspec đó quy định cụ thể mà submodules nên tồn tại trong cây làm việc.
    • Các submodule.<name>.activecấu hình là cờ boolean sử dụng để chỉ nếu đó submodule đặc biệt nên tồn tại trong cây làm việc.

Điều quan trọng cần lưu ý là submodule.activehoạt động khác với các tùy chọn cấu hình khác vì nó sử dụng một pathspec.
Điều này cho phép người dùng áp dụng ít nhất hai quy trình công việc mới:

  1. Các mô-đun con có thể được nhóm lại với một thư mục hàng đầu, sao cho một pathspec, ví dụ: ' lib/' sẽ bao gồm tất cả các mô-đun thư viện-ish để cho phép những người quan tâm đến mô-đun thư viện ish đặt " submodule.active = lib/" chỉ một lần để nói bất kỳ và tất cả các mô-đun trong ' lib/' là hấp dẫn.
  2. Khi tính năng thuộc tính pathspec được phát minh, người dùng có thể gắn nhãn các mô-đun con với các thuộc tính để nhóm chúng lại, do đó, một pathspec rộng với các yêu cầu thuộc tính, ví dụ: ' :(attr:lib)', có thể được sử dụng để nói rằng bất kỳ và tất cả các mô-đun có libthuộc tính '' đều thú vị.
    .gitattributestệp, giống như .gitmodulestệp, được theo dõi bởi siêu dự án, khi một mô-đun con di chuyển trong cây siêu dự án, dự án có thể điều chỉnh đường dẫn nào nhận thuộc tính .gitattributes, giống như nó có thể điều chỉnh đường dẫn nào có mô-đun con trong đó .gitmodules.

Làm thế nào để tìm chính xác <name>cho một mô-đun con trong một dự án hiện có?
ideasman42

@ ideaman42 Đọc cấu hình trong .gitmodules sẽ hữu ích: stackoverflow.com/a/12641787/6309
VonC

Ah nó chỉ là giá trị từ .git/config->[submodule "<name>"]
ideasman42

1
Không làm việc cho tôi. Đây là những gì tôi làm: 1) git clone với --recursive; 2) đặt cấu hình git làm câu trả lời; 3) làm git checkout, git pull để kiểm tra submodule cuối cùng; Vẫn nhận được "(cam kết mới)".
Wu Baiquan

2
@VonC Trước khi nhắn tin cho bạn, tôi đã thử cả hai (với repo hiện có cũng như repo mới khởi tạo), cả hai trường hợp đều không hoạt động.
Porcupine

3

Câu trả lời Nevik Rehnel chắc chắn là câu trả lời chính xác cho những gì bạn đang hỏi: Tôi không muốn có một mô-đun con, làm cách nào để thoát khỏi tình huống đó ?! .

Chỉ, nếu masterdự án của bạn yêu cầu bookmô-đun con, thì đó là một cử chỉ tốt để giữ nó như vậy vì theo cách đó những người dùng khác đã kiểm tra dự án của bạn sau đó có thể thích không có bất kỳ gitlệnh đặc biệt nào để chạy (tốt ... có một số lệnh đặc biệt để sử dụng mô-đun con, nhưng tôi nghĩ về tổng thể vẫn đơn giản hơn để quản lý.)

Trong trường hợp của bạn, bạn thực hiện các thay đổi trong bookkho lưu trữ và tại một thời điểm nào đó bạn thực hiện các thay đổi đó. Điều này có nghĩa là bạn có các cam kết mới trong mô-đun con đó, có một tham chiếu SHA1 mới.

Những gì bạn cần làm trong thư mục chính là cam kết những thay đổi đó trong kho lưu trữ chính.

cd /path/to/master
git commit . -m "Update 'book' in master"

Thao tác này sẽ cập nhật tham chiếu SHA1 masterlên phiên bản mới nhất có sẵn trong bookkho lưu trữ. Kết quả là cam kết này cho phép những người khác kiểm tra tất cả master& bookkho lưu trữ ở đầu.

Vì vậy, trên thực tế, bạn kết thúc với một cam kết nữa bất cứ khi nào bạn thực hiện thay đổi đối với một mô-đun con. Nó là nửa công khai nếu bạn cũng thực hiện các thay đổi đối với một số tệp trong masterkho lưu trữ vì bạn cam kết cả hai cùng một lúc.


-5

Chạy

git submodule update 

ở cấp cơ sở.


Chỉ dành cho bất cứ ai thắc mắc. Trong trường hợp của tôi (và OP?), Điều này không thay đổi những gì đã git statusnói. Nó vẫn nghĩ rằng những thay đổi đã xảy ra.
squarism

Việc sao chép câu trả lời của người khác là một việc làm rất tệ
Maxim
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.