Thư mục con thanh toán trong Git?


160

Có thể kiểm tra thư mục con của kho lưu trữ trong Git không?

Hãy tưởng tượng tôi đang thiết lập một cài đặt WordPress mới. Tôi sẽ tạo hai thư mục mới cho tùy chỉnh plugin và chủ đề của mình:

  • wordpress/wp-content/plugins/myplugins/
  • wordpress/wp-content/themes/mytheme/

Tôi muốn duy trì các thư mục này thông qua Git. Trong Subversion, tôi sẽ thực hiện điều này bằng cách có trunk/myplugins/và các trunk/mytheme/thư mục và kiểm tra các thư mục con. Git có cách nào để hoàn thành nhiệm vụ tương tự bằng cách sử dụng một kho lưu trữ không?

Tôi chỉ có thể thiếu thuyền trên một số mô hình Git, vì một người dùng SVN lâu năm ít tiếp xúc với Git.

Chỉnh sửa: Nhiều chi nhánh lưu trữ nội dung khác nhau là một cách thú vị để xử lý việc này.


2
Tại sao bạn không kiểm tra toàn bộ repo và tạo một liên kết tượng trưng đến các thư mục con bạn muốn làm việc?
ngẫu nhiên2077



Có thể thực hiện kiểm tra thưa thớt và kho Git tham chiếu không?
luka5z

Câu trả lời:


121

Thanh toán thưa thớtbây giờ trong Git 1,7 .

Ngoài ra, hãy xem câu hỏi Có thể thực hiện kiểm tra thưa thớt mà không cần kiểm tra toàn bộ kho lưu trữ trước không? Mùi.

Lưu ý rằng kiểm tra thưa thớt vẫn yêu cầu bạn tải xuống toàn bộ kho lưu trữ, mặc dù một số tệp Git tải xuống sẽ không kết thúc trong cây làm việc của bạn.


1
git cloneLệnh de đơn giản ở đâu ?? Vâng, tôi sử dụng câu trả lời này , đang làm việc!
Peter Krauss

4
Và có cách nào để đổi tên các thư mục đó không? Nếu tôi kiểm tra thưa thớt /foo/bar/foobar, có thể chỉ nhìn thấy nó như /foobartrong kho lưu trữ cục bộ của tôi không?
Graywolf

17

Không có cách thực sự để làm điều đó trong git. Và nếu bạn sẽ không thực hiện các thay đổi ảnh hưởng đến cả hai cây cùng một lúc như một đơn vị công việc, thì không có lý do chính đáng để sử dụng một kho lưu trữ duy nhất cho cả hai. Tôi nghĩ rằng tôi sẽ bỏ lỡ tính năng Subversion này, nhưng tôi thấy rằng việc tạo các kho lưu trữ có quá ít chi phí quản lý tinh thần (đơn giản là do các kho lưu trữ được lưu trữ ngay bên cạnh bản sao làm việc của chúng, thay vì yêu cầu tôi phải chọn một nơi rõ ràng bên ngoài bản sao làm việc) mà tôi đã quen với việc tạo ra nhiều kho lưu trữ đơn mục đích nhỏ.

Nếu bạn nhấn mạnh (hoặc thực sự cần nó), tuy nhiên, bạn có thể làm một kho git với chỉ mythememypluginsdanh bạ và symlink những từ bên trong WordPress cài đặt.


MDCore đã viết:

thực hiện một cam kết, ví dụ, huyền thoại sẽ tăng số sửa đổi cho myplugin

Lưu ý rằng đây không phải là vấn đề đáng lo ngại đối với git, nếu bạn quyết định đặt cả hai thư mục vào một kho lưu trữ, bởi vì git hoàn toàn không có khái niệm về số lần sửa đổi tăng đơn điệu dưới mọi hình thức.

Tiêu chí duy nhất cho những thứ cần kết hợp trong một kho lưu trữ duy nhất trong git là liệu nó có tạo thành một đơn vị hay không, nghĩa là. trong trường hợp của bạn cho dù có những thay đổi trong đó không có ý nghĩa khi xem xét các chỉnh sửa trong mỗi thư mục một cách riêng biệt. Nếu bạn có các thay đổi khi bạn cần chỉnh sửa các tệp trong cả hai thư mục cùng một lúc và các chỉnh sửa thuộc về nhau, chúng phải là một kho lưu trữ. Nếu không, sau đó không glom chúng với nhau.

Git thực sự thực sự muốn bạn sử dụng các kho riêng cho các thực thể riêng biệt.

mô đun con

Các mô hình con không giải quyết mong muốn giữ cả hai thư mục trong một kho lưu trữ, bởi vì chúng thực sự sẽ thực thi việc có một kho lưu trữ riêng cho mỗi thư mục, sau đó được kết hợp trong một kho lưu trữ khác bằng cách sử dụng các mô đun con. Tồi tệ hơn, vì các thư mục trong bản cài đặt WordPress không phải là thư mục con trực tiếp của cùng thư mục và cũng là một phần của hệ thống phân cấp với nhiều tệp khác, sử dụng kho lưu trữ trên mỗi thư mục làm tệp con trong kho lưu trữ hợp nhất sẽ không mang lại lợi ích gì, bởi vì hợp nhất kho lưu trữ sẽ không phản ánh bất kỳ trường hợp sử dụng / nhu cầu.


Trường hợp git clonetrình tự lệnh đơn giản ?? Vâng, tôi sử dụng câu trả lời này , đang làm việc!
Peter Krauss

16

Một điều tôi không thích về kiểm tra thưa thớt, là nếu bạn muốn kiểm tra một thư mục con sâu một vài thư mục, cấu trúc thư mục của bạn phải chứa tất cả các thư mục dẫn đến nó.

Cách tôi làm việc này là sao chép repo ở một nơi không phải là không gian làm việc của tôi và sau đó tạo một liên kết tượng trưng trong thư mục không gian làm việc của tôi đến thư mục con trong kho lưu trữ. Git hoạt động như thế này khá độc đáo vì những thứ như trạng thái git sẽ hiển thị các tệp thay đổi liên quan đến thư mục làm việc hiện tại của bạn.


Điều này chỉ hoạt động trong một hệ điều hành hỗ trợ các liên kết tượng trưng. Họ cần thay đổi cách kiểm tra thưa thớt hoạt động.
Anders Lindén

1
+1 cho ý tưởng với một liên kết tượng trưng trên thư mục đã kiểm tra. Tuy nhiên, thanh toán thưa thớt và liên kết tượng trưng không loại trừ lẫn nhau: bạn không cần một bản sao đầy đủ.
apitsch

10

Trên thực tế, kiểm tra "hẹp" hoặc "một phần" hoặc "thưa thớt" đang được phát triển mạnh mẽ hiện tại cho Git. Lưu ý, bạn vẫn sẽ có kho lưu trữ đầy đủ bên dưới .git. Vì vậy, hai bài đăng khác là hiện tại cho trạng thái Git hiện tại nhưng có vẻ như chúng ta sẽ có thể thực hiện kiểm tra thưa thớt cuối cùng. Kiểm tra danh sách gửi thư nếu bạn quan tâm đến nhiều chi tiết hơn - chúng đang thay đổi nhanh chóng.


Tốt để biết! Tôi thích có các thư mục liên quan chặt chẽ như vậy trong một kho lưu trữ, và sẽ làm điều đó nếu có thể.
Annika Backstrom

5

git clone --filter từ Git 2.19

Tùy chọn này thực sự sẽ bỏ qua việc tìm nạp các đối tượng không cần thiết từ máy chủ:

git clone --depth 1 --no-checkout --filter=blob:none \
  "file://$(pwd)/server_repo" local_repo
cd local_repo
git checkout master -- mdir/

Máy chủ nên được cấu hình với:

git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

Không có hỗ trợ máy chủ kể từ v2.19.0, nhưng nó đã có thể được kiểm tra cục bộ.

file://$(path)được yêu cầu để vượt qua git clonecác shenanigans giao thức: Làm thế nào để sao chép một kho lưu trữ git cục bộ với một đường dẫn tương đối?

Hãy nhớ điều đó --depth 1đã ngụ ý --single-branch, xem thêm: Làm cách nào để sao chép một nhánh duy nhất trong Git?

TODO: --filter=blob:nonebỏ qua tất cả các đốm màu, nhưng vẫn tìm nạp tất cả các đối tượng cây. Nhưng trên một repo bình thường, nó sẽ rất nhỏ so với các tệp, vì vậy điều này đã đủ tốt rồi. Đã hỏi tại: https://www.spinics.net/lists/git/msg342006.html Devs trả lời a --filter=tree:0đang trong công việc để làm điều đó.

Các định dạng của --filtertài liệu trên man git-rev-list.

Một phần mở rộng đã được thực hiện cho giao thức từ xa Git để hỗ trợ tính năng này.

Tài liệu trên cây Git:

Kiểm tra nó ra

#!/usr/bin/env bash
set -eu

list-objects() (
  git rev-list --all --objects
  echo "master commit SHA: $(git log -1 --format="%H")"
  echo "mybranch commit SHA: $(git log -1 --format="%H")"
  git ls-tree master
  git ls-tree mybranch | grep mybranch
  git ls-tree master~ | grep root
)

# Reproducibility.
export GIT_COMMITTER_NAME='a'
export GIT_COMMITTER_EMAIL='a'
export GIT_AUTHOR_NAME='a'
export GIT_AUTHOR_EMAIL='a'
export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'

rm -rf server_repo local_repo
mkdir server_repo
cd server_repo

# Create repo.
git init --quiet
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1

# First commit.
# Directories present in all branches.
mkdir d1 d2
printf 'd1/a' > ./d1/a
printf 'd1/b' > ./d1/b
printf 'd2/a' > ./d2/a
printf 'd2/b' > ./d2/b
# Present only in root.
mkdir 'root'
printf 'root' > ./root/root
git add .
git commit -m 'root' --quiet

# Second commit only on master.
git rm --quiet -r ./root
mkdir 'master'
printf 'master' > ./master/master
git add .
git commit -m 'master commit' --quiet

# Second commit only on mybranch.
git checkout -b mybranch --quiet master~
git rm --quiet -r ./root
mkdir 'mybranch'
printf 'mybranch' > ./mybranch/mybranch
git add .
git commit -m 'mybranch commit' --quiet

echo "# List and identify all objects"
list-objects
echo

# Restore master.
git checkout --quiet master
cd ..

# Clone. Don't checkout for now, only .git/ dir.
git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
cd local_repo

# List missing objects from master.
echo "# Missing objects after --no-checkout"
git rev-list --all --quiet --objects --missing=print
echo

echo "# Git checkout fails without internet"
mv ../server_repo ../server_repo.off
! git checkout master
echo

echo "# Git checkout fetches the missing directory from internet"
mv ../server_repo.off ../server_repo
git checkout master -- d1/
echo

echo "# Missing objects after checking out d1"
git rev-list --all --quiet --objects --missing=print

GitHub ngược dòng .

Đầu ra trong Git v2.19:

# List and identify all objects
c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
fc5e97944480982cfc180a6d6634699921ee63ec
7251a83be9a03161acde7b71a8fda9be19f47128
62d67bce3c672fe2b9065f372726a11e57bade7e
b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
84de03c312dc741d0f2a66df7b2f168d823e122a d2
0975df9b39e23c15f63db194df7f45c76528bccb d2/a
41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
ef29f15c9a7c5417944cc09711b6a9ee51b01d89
19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
a0234da53ec608b54813b4271fbf00ba5318b99f root
93ca1422a8da0a9effc465eccbcb17e23015542d root/root
master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75    d1
040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a    d2
040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3    master
040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043    mybranch
040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f    root

# Missing objects after --no-checkout
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
?308150e8fddde043f3dbbb8573abb6af1df96e63

# Git checkout fails without internet
fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

# Git checkout fetches the missing directory from internet
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.

# Missing objects after checking out d1
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb

Kết luận: tất cả các đốm màu từ bên ngoài d1/bị thiếu.

Lưu ý rằng root/rootmybranch/mybranchcũng bị thiếu, nhưng --depth 1ẩn nó khỏi danh sách các tệp bị thiếu. Nếu bạn loại bỏ --depth 1, sau đó họ hiển thị trên danh sách các tập tin bị thiếu.


1

Khi chỉnh sửa của bạn chỉ ra, bạn có thể sử dụng hai nhánh riêng biệt để lưu trữ hai thư mục riêng biệt. Điều này không giữ cả hai trong cùng một kho lưu trữ, nhưng bạn vẫn không thể có các cam kết bao trùm cả hai cây thư mục. Nếu bạn có một thay đổi trong một yêu cầu thay đổi khác, bạn sẽ phải thực hiện những thay đổi đó như hai cam kết riêng biệt và bạn mở ra khả năng một cặp thanh toán của hai thư mục có thể không đồng bộ.

Nếu bạn muốn coi cặp thư mục là một đơn vị, bạn có thể sử dụng 'wordpress / wp-content' làm gốc của repo của bạn và sử dụng tệp .gitignore ở cấp cao nhất để bỏ qua mọi thứ trừ hai thư mục con quan tâm. Đây có lẽ là giải pháp hợp lý nhất vào thời điểm này.

Thanh toán thưa thớt đã bị cáo buộc đến từ hai năm nay, nhưng vẫn không có dấu hiệu nào của chúng trong repo phát triển git, cũng không có dấu hiệu nào cho thấy những thay đổi cần thiết sẽ đến đó. Tôi sẽ không tin tưởng vào họ.


1

Bạn không thể kiểm tra một thư mục duy nhất của kho lưu trữ vì toàn bộ kho được xử lý bởi thư mục .git duy nhất trong thư mục gốc của dự án thay vì vô số thư mục .svn.

Vấn đề với việc làm việc trên các plugin trong một kho lưu trữ duy nhất là việc thực hiện một cam kết, ví dụ, huyền thoại sẽ tăng số sửa đổi cho myplugin , vì vậy ngay cả khi lật đổ, tốt hơn là sử dụng các kho lưu trữ riêng biệt.

Mô hình lật đổ cho các dự án con là svn: externals dịch phần nào thành các mô đun con trong git (nhưng không chính xác trong trường hợp bạn đã sử dụng svn: externals trước đó.)


0

Có một nguồn cảm hứng ở đây. Chỉ cần sử dụng shell regexhoặc git regex.

git checkout commit_id */*.bat  # *.bat in 1-depth subdir exclude current dir, shell regex  
git checkout commit_id '*.bat'  # *.bat in all subdir include current dir, git regex

Sử dụng trích dẫn để thoát khỏi giải thích regex shell và truyền ký tự đại diện cho git.

Cái đầu tiên không được đệ quy, chỉ có các tệp ở độ sâu 1 subdir. Nhưng cái thứ hai là đệ quy.

Đối với tình huống của bạn, sau đây có thể là đủ.

git checkout master */*/wp-content/*/*
git checkout master '*/wp-content/*'

Chỉ cần hack các dòng theo yêu cầu.


0

Bạn chỉ có thể hoàn nguyên các thay đổi không được cam kết đối với tệp hoặc thư mục cụ thể:

git checkout [some_dir|file.txt]
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.