Làm cách nào để thêm thư mục trống vào kho Git?


4267

Làm cách nào để thêm thư mục trống (không chứa tệp) vào kho Git?


16
Mặc dù nó không hữu ích, nhưng có một cách để hack một thư mục trống (thực sự trống) vào repo của bạn . Tuy nhiên, nó sẽ không checkoutcó phiên bản hiện tại của Git.
tiwo

335
@tiwo Tôi không đồng ý rằng nó không hữu ích. Hệ thống phân cấp thư mục của bạn là một phần của dự án của bạn, vì vậy nó phải được kiểm soát phiên bản.
JBentley

114
Trong trường hợp của tôi, tôi muốn thêm cấu trúc thư mục cho các tệp tmp, nhưng không phải là các tệp tmp. Bằng cách này, người kiểm tra của tôi có cấu trúc chính xác (nếu không có lỗi) nhưng tôi không làm tắc nghẽn các cam kết của mình với dữ liệu tmp. Vì vậy, có, nó hữu ích cho tôi!
Adam Marshall

45
@AdamMarshall Tôi nghĩ rằng tiwo đã nói rằng hack không hữu ích, vì nó bị bỏ qua khi thanh toán. Các thư mục Tmp có vẻ như là một tính năng hữu ích cho một VCS.
Quantum7

31
Tại sao không có thủ tục tạo tập tin tmp cũng tạo thư mục tmp?
RyPeck

Câu trả lời:


4128

Một cách khác để làm cho một thư mục ở lại (gần như) trống (trong kho lưu trữ) là tạo một .gitignoretệp bên trong thư mục chứa bốn dòng này:

# Ignore everything in this directory
*
# Except this file
!.gitignore

Sau đó, bạn không cần phải đặt hàng đúng cách mà bạn phải làm trong giải pháp của m104 .

Điều này cũng mang lại lợi ích là các tệp trong thư mục đó sẽ không hiển thị là "không bị theo dõi" khi bạn thực hiện trạng thái git.

Làm cho bình luận của @GreenAsJade vẫn tồn tại:

Tôi nghĩ rằng đáng chú ý là giải pháp này thực hiện chính xác những gì câu hỏi yêu cầu, nhưng có lẽ không phải là điều mà nhiều người nhìn vào câu hỏi này sẽ tìm kiếm. Giải pháp này đảm bảo rằng thư mục vẫn trống. Nó nói "Tôi thực sự không bao giờ muốn các tập tin được kiểm tra ở đây". Trái ngược với "Tôi chưa có bất kỳ tệp nào để đăng ký tại đây, nhưng tôi cần thư mục ở đây, các tệp có thể đến sau".


25
Tôi nghĩ rằng giải pháp README được đề xuất bởi @JohnMee nên được sử dụng cùng với giải pháp này; tệp .gitignore cung cấp giải thích về những gì chúng tôi muốn tránh khỏi kiểm soát phiên bản, trong khi tệp README giải thích mục đích của thư mục là gì, cả hai đều là những thông tin rất quan trọng.
pedromanoel

18
@pedromanoel Tôi viết tài liệu bạn sẽ đặt vào READMEbên trong .gitignoretệp (dưới dạng nhận xét).
Carlos Campderrós

69
phát hiện sự khác biệt 1: 1.) một thư mục trống, 2.) một thư mục có tệp .gitignore trong đó. ;-)
Peter Perháč

6
Điều này là hoàn hảo cho các thư mục bộ nhớ cache .
hương thơm

10
Thật không may, điều này dẫn đến một thư mục không trống, nó có một tập tin ẩn duy nhất.
pedorro

1091

Bạn không thể. Xem Câu hỏi thường gặp về Git .

Hiện tại, việc thiết kế chỉ số git (khu vực tổ chức) chỉ cho phép các tệp được liệt kê và không ai đủ thẩm quyền để thực hiện thay đổi để cho phép các thư mục trống đã quan tâm đủ về tình huống này để khắc phục.

Thư mục được thêm tự động khi thêm tệp bên trong chúng. Đó là, các thư mục không bao giờ phải được thêm vào kho lưu trữ và không được theo dõi riêng.

Bạn có thể nói " git add <dir>" và nó sẽ thêm các tập tin vào đó.

Nếu bạn thực sự cần một thư mục tồn tại trong thanh toán, bạn nên tạo một tệp trong đó. .gitignore hoạt động tốt cho mục đích này; bạn có thể để trống hoặc điền vào tên của các tệp bạn muốn hiển thị trong thư mục.


67
Dưới đây câu trả lời là NHIỀU tốt hơn. Thực tế là git phần mềm cấp thấp không cho phép nó không quan trọng bằng CÁCH sử dụng Git khi tôi cần một thư mục trống. Thêm một dòng .gitignore có vẻ chấp nhận được với tôi.
Amala

1
Chà, nếu ai đó muốn chuyển các tập tin vào một thư mục mới, họ không thể thực hiện được git mvvì git sẽ phàn nàn rằng thư mục mới không nằm dưới sự kiểm soát phiên bản
lulalala

16
Bạn có thể đọc " không thể, bạn không thể, v.v. " trên Internet cho câu hỏi thường gặp này. Các .gitignoreBí quyết là một câu trả lời thường xuyên, và đáp ứng nhiều nhu cầu. Tuy nhiên , có thể làm cho git theo dõi một thư mục thực sự trống rỗng , xem câu trả lời của tôi
ofavre

2
Mặc dù tôi càng nghĩ về nó, tôi càng cảm thấy "Băm SHA của chuỗi rỗng", nếu nó tồn tại, thực sự sẽ là một định danh được xác định rõ cho một cây trống, trừ khi không thể biết liệu đối tượng đó có phải là một cái cây hoặc một đốm màu
Emil Lundberg

21
Tôi đã thấy rất nhiều repos sử dụng một tập tin trống được gọi .gitkeepcho mục đích này.
Sukima

759

Tạo một tập tin trống được gọi .gitkeeptrong thư mục và thêm nó.


58
Tôi đã thêm một câu trả lời khuyến khích để tạo ra .keepthay thế.
Acumenus

206
.gitkeepđã không được Git quy định và sẽ khiến mọi người đoán lần thứ hai về ý nghĩa của nó, điều này sẽ dẫn họ đến các tìm kiếm google, điều này sẽ dẫn họ đến đây. Quy .gitước tiền tố nên được dành riêng cho các tệp và thư mục mà chính Git sử dụng.
t-mart

10
@ t-mart "Quy .gitước tiền tố nên được bảo lưu ..." Tại sao? Có git yêu cầu đặt phòng này?
Chuộc tội có giới hạn

9
Trong trường hợp này một READMEhoặc ABOUTtập tin sẽ chỉ là tốt hoặc tốt hơn. Để lại một ghi chú cho anh chàng tiếp theo, giống như tất cả chúng ta đã từng làm điều đó trước URL.
Dave

5
Không hoạt động nếu bạn đang viết một bài kiểm tra đơn vị nên kiểm tra mã trên một thư mục trống ...
thebjorn

437

Bạn luôn có thể đặt một tệp README trong thư mục với lời giải thích lý do tại sao bạn muốn thư mục này, nếu không, trống trong kho lưu trữ.


39
+1, Gợi ý tốt, một thư mục trống không có ý nghĩa gì trừ khi nó sẽ được sử dụng trong tương lai. Vì vậy, hãy tạo một tệp README bên trong nó và viết thư mục này để làm gì, và những tệp nào sẽ được đặt ở đó trong tương lai. Điều đó giải quyết cả hai vấn đề.
saeedgnu

63
@ilius Vô nghĩa. Cấu trúc thư mục chứa các thư mục trống có thể rất được mong muốn trong nhiều trường hợp (như ứng dụng MVC trong đó bạn muốn có thư mục mô hình nhưng chưa tìm được cách tạo bất kỳ mô hình nào hoặc thư mục chế độ xem được chia sẻ mà bạn dự định thêm lượt xem được chia sẻ vào sau ). Hơn nữa, việc đặt README vào mỗi một trong số này là quá mức cần thiết vì rõ ràng những gì họ đang ở đó và thật dễ dàng để quên README trong mỗi một trong số họ. VÀ bạn phải nhớ xóa README khi bạn thêm một số tệp khác vào chúng. Về cơ bản, git chắc chắn nên cho phép các thư mục trống.
Jez

20
@Jez: Tôi không đồng ý. Vấn đề là git được thiết kế để kiểm soát (và lập chỉ mục) mã nguồn. Điều quan trọng, id của một cam kết là một hàm băm của nội dung. Đó là để nói, nó phải có nội dung. Bạn không cần README trong mỗi phần của cây, chỉ các nút lá. Nếu bạn có địa điểm bạn định đặt mã, nhưng không có mã và thậm chí bạn sẽ không dành thời gian để lặp lại "địa điểm cho các mô hình" >> README, thì những gì bạn có là một ý tưởng không phải là một cam kết. Nó không phải là quan tâm đến git. Nói rằng "Tôi muốn ứng dụng đang chạy có các thư mục trống XYZ" là một vấn đề thời gian chạy , không phải là vấn đề nguồn. Xử lý nó với trình cài đặt của bạn.
Joe Atzberger

6
@JoeAtzberger Đây là một tính năng còn thiếu, không phải là giới hạn có chủ ý. Từ Câu hỏi thường gặp về Git: Hiện tại thiết kế chỉ mục Git (khu vực tổ chức) chỉ cho phép các tệp được liệt kê và không ai đủ thẩm quyền để thực hiện thay đổi để cho phép các thư mục trống đã quan tâm đủ về tình huống này để khắc phục.
jbo5112

7
@ jbo5112 Có, "mã đặc biệt" mà bạn đề cập đến là "trình cài đặt" mà tôi đã đề cập. Cài đặt ứng dụng web của bạn đã phải xử lý việc tạo cơ sở dữ liệu, cấu hình cục bộ, kéo phụ thuộc hoặc 100 thao tác khác, nhưng một vài thư mục trống nằm ngoài nó? Hãy thử gradle, hành khách, đầu bếp, một Makefile nguyên thủy, v.v. Không có sự khác biệt về bảo mật giữa việc tạo các thư mục và công việc khác (có thể phức tạp / nguy hiểm hơn nhiều) khi cài đặt một ứng dụng. Và nếu bạn thực sự không có deps, config, DB, v.v. và không có trình cài đặt, thì chỉ cần sử dụng README. Không có trường hợp nào yêu cầu bạn phải làm cả hai.
Joe Atzberger

349
touch .keep

Trên Linux, điều này tạo ra một tệp trống có tên .keep. Đối với những gì nó có giá trị, tên này là bất khả tri đối với Git, trong khi đó .gitkeepsẽ là cụ thể cho Git. Thứ hai, như một người dùng khác đã lưu ý, .gitquy ước tiền tố nên được dành riêng cho các tệp và thư mục mà chính Git sử dụng.

Ngoài ra, như được lưu ý trong một câu trả lời khác , thư mục có thể chứa một mô tả READMEhoặc README.mdtập tin thay thế.

Tất nhiên, điều này đòi hỏi sự hiện diện của tệp sẽ không khiến ứng dụng của bạn bị hỏng.


1
Điều này tốt cho một thư mục trống ban đầu, nhưng nếu nó bắt đầu điền vào các tập tin thì sao? Sau đó, Git sẽ chú ý đến chúng và tuyên bố chúng là các tệp không bị theo dõi. Câu trả lời được chọn ở đây hoạt động thanh lịch hơn nhiều để cho phép một người giữ một thư mục nhưng sau đó bỏ qua các nội dung một cách an toàn.
JakeGould

14
Câu hỏi và mối quan tâm chung chủ yếu là về việc thêm một thư mục trống. Nếu sau này có tệp thường trú, rõ ràng xóa .keeptệp hoặc chỉ cần bỏ qua nó. Nếu thay vào đó, các tập tin trong thư mục sẽ bị bỏ qua, đó là một câu hỏi hoàn toàn khác.
Acumenus

3
Nó đã được đề xuất rằng git clean -nd | sed s/'^Would remove '// | xargs -I{} touch "{}.keep"sẽ làm điều này trong tất cả các thư mục trống chưa được theo dõi.
Acumenus

1
Đừng thích giải pháp này, thật khó để đoán tập tin này làm gì. Ngoài ra, nếu bạn đang tạo các tệp trong môi trường dev của mình (như nhật ký hoặc hình ảnh, v.v.), thì điều này sẽ không giữ cho các tệp đó không được phiên bản và đưa chúng vào sản xuất, điều này không tốt.
danielrvt

1
Windows không thích các tệp không có tên và yêu cầu phép thuật đặc biệt để thực hiện điều này (còn gọi là ứng dụng đầu cuối giống như bash hoặc tương đương).
EntangledLoops

303

Tại sao chúng ta cần các thư mục phiên bản trống

Điều đầu tiên trước tiên:

Một thư mục trống không thể là một phần của cây trong hệ thống phiên bản Git .

Nó chỉ đơn giản là sẽ không được theo dõi. Nhưng có những kịch bản trong đó các thư mục trống "phiên bản" có thể có ý nghĩa, ví dụ:

  • dàn dựng một cấu trúc thư mục được xác định trước , làm cho nó có sẵn cho mọi người dùng / người đóng góp của kho lưu trữ; hoặc, như một trường hợp chuyên biệt ở trên, tạo thư mục cho các tệp tạm thời , chẳng hạn như cache/hoặc logs/thư mục, nơi chúng tôi muốn cung cấp thư mục nhưng .gitignorenội dung của nó
  • Liên quan đến vấn đề trên, một số dự án sẽ không hoạt động nếu không có một số thư mục (thường là gợi ý của một dự án được thiết kế kém, nhưng đó là một kịch bản trong thế giới thực thường xuyên và có thể có vấn đề về quyền được giải quyết).

Một số cách giải quyết được đề xuất

Nhiều người dùng đề xuất:

  1. Đặt một READMEtệp hoặc một tệp khác với một số nội dung để làm cho thư mục không trống, hoặc
  2. Tạo một .gitignoretệp với một loại "logic đảo ngược" (nghĩa là bao gồm tất cả các tệp), ở cuối, phục vụ cùng một mục đích của cách tiếp cận # 1.

Trong khi cả hai giải pháp chắc chắn hoạt động, tôi thấy chúng không phù hợp với cách tiếp cận có ý nghĩa đối với phiên bản Git.

  • Tại sao bạn phải đặt các tệp không có thật hoặc README mà có thể bạn không thực sự muốn trong dự án của mình?
  • Tại sao sử dụng .gitignoređể làm một việc ( giữ các tệp) trái ngược với ý nghĩa của nó ( không bao gồm các tệp), mặc dù điều đó là có thể?

phương pháp tiếp cận

Sử dụng một tệp trống được gọi .gitkeepđể buộc sự hiện diện của thư mục trong hệ thống phiên bản.

Mặc dù nó có vẻ không phải là một sự khác biệt lớn như vậy:

  • Bạn sử dụng một tệp có mục đích duy nhất là giữ thư mục. Bạn không đặt ở đó bất kỳ thông tin nào bạn không muốn đặt.

    Chẳng hạn, bạn cũng nên sử dụng READMEs, READMEs với thông tin hữu ích, không phải là lý do để giữ thư mục.

    Tách biệt các mối quan tâm luôn là một điều tốt, và bạn vẫn có thể thêm một .gitignoređể bỏ qua các tệp không mong muốn.

  • Việc đặt tên này .gitkeeplàm cho nó rất rõ ràng và đơn giản từ chính tên tệp (và cả các nhà phát triển khác , điều này tốt cho một dự án được chia sẻ và một trong những mục đích cốt lõi của kho lưu trữ Git) rằng tệp này là

    • Một tệp không liên quan đến mã (vì dấu chấm và tên hàng đầu)
    • Một tập tin rõ ràng liên quan đến Git
    • Mục đích của nó ( giữ ) được nêu rõ ràng và nhất quán và trái ngược về mặt ngữ nghĩa trong việc bỏ qua

Con nuôi

Tôi đã thấy .gitkeepcách tiếp cận được áp dụng bởi các khung rất quan trọng như Laravel , Angular-CLI .


8
Bạn đã bỏ lỡ một suy nghĩ - lý do để giữ và thư mục trống (ví dụ: / log, / tmp, / tải lên)? Có - để giữ thư mục trống. :) Vì vậy, nếu bạn muốn giữ một thư mục trống, bạn phải bỏ qua các tệp bên trong nó.
La Mã

14
@Roman ALLenstein: không nhất thiết. Có thể là bạn tạo một repo với cấu trúc nhất định có thể trở nên phổ biến sau này. Các tệp đó sẽ được thêm vào repo ngay khi chúng được tạo và sẽ rất khó chịu khi bắt đầu xóa hoặc chỉnh sửa các tệp .gitignore (và nguy hiểm, vì có lẽ bạn thậm chí không nhận ra rằng chúng không bị theo dõi: git đang bỏ qua chúng )
blueFast 17/2/2015

45
@Behnam: Tôi sẽ sử dụng downvote, nhưng nghiên cứu của tôi về meta SO cho thấy không có mối quan tâm nào đối với câu trả lời dài dòng, miễn là chúng cung cấp đủ chi tiết và rõ ràng để hữu ích cho mọi người đọc (và mọi cấp độ kỹ năng). Tôi vẫn rất cởi mở với bất kỳ lời chỉ trích nào và cảm ơn bạn vì đã tuyên bố lý do công khai, tôi rất tích cực.
Cranio

4
Nếu bạn chỉnh sửa câu trả lời của mình để thay thế .gitkeepbằng bất kỳ tên tệp không có tiền tố nào khác, bạn sẽ nhận được upvote của mình, tôi nghĩ đây là câu trả lời hay nhất và nhiều thông tin nhất. Lý do: Tôi nghĩ rằng ".git *" nên được dành riêng cho các tệp theo quy định của git, trong khi đây chỉ là một trình giữ chỗ đơn thuần. Suy đoán đầu tiên của tôi khi tôi thấy đó là ví dụ: tệp ".gitkeep" sẽ tự động bị bỏ qua (đó sẽ là một tính năng hay) nhưng đó không phải là trường hợp, phải không?
Johnny

5
Tôi tự hỏi tại sao mọi người có một thời gian khó khăn để hiểu tại sao một người muốn thêm các thư mục "trống" vào git. Bạn phải bắt đầu ở đâu đó, phải không? Vì vậy, thông thường bạn bắt đầu với cấu trúc thư mục dự án của bạn và - than ôi - khi bắt đầu dự án vẫn chưa có gì. Khi repo dự án của bạn được thực hiện, nhân viên nhóm có thể sao chép và bắt đầu làm việc trên cấu trúc CÙNG.
BitTickler

127

Như được mô tả trong các câu trả lời khác, Git không thể biểu thị các thư mục trống trong khu vực tổ chức. (Xem Câu hỏi thường gặp về Git .) Tuy nhiên, nếu, với mục đích của bạn, một thư mục đủ trống nếu nó chỉ chứa một .gitignoretệp, thì bạn chỉ có thể tạo .gitignoretệp trong các thư mục trống thông qua:

find . -type d -empty -exec touch {}/.gitignore \;

21
Bạn có thể muốn bỏ qua thư mục .git: find . -name .git -prune -o -type d -empty -exec touch {}/.gitignore \;
steffen

3
Một biến thể đơn giản hơn cho hầu hết các tình huống làfind * -type d -empty -exec touch {}/.gitignore \;
akhan

2
Vì OS X tạo tệp .DS_Store trong hầu hết mọi directoy, nên điều này không hoạt động ở đó. Cách giải quyết duy nhất (NGUY HIỂM!) Mà tôi tìm thấy, là xóa tất cả các tệp .DS_Store trước find . -name .DS_Store -exec rm {} \;và sau đó sử dụng biến thể ưa thích từ câu trả lời này. Hãy chắc chắn chỉ thực hiện điều này trong thư mục chính xác!
zerweck

1
Có ai biết một cách để làm điều này trong Windows từ dòng lệnh không? Tôi đã thấy một số giải pháp ở đây trong Ruby và Python, nhưng tôi muốn một giải pháp barebones nếu nó có thể được quản lý.
Mig82

1
@akhan Thêm một cái gì đó .gitignorekhông có ảnh hưởng đến -emptycờ của findlệnh. Nhận xét của tôi là về việc loại bỏ các .DS_Storetệp trong cây thư mục, vì vậy -emptycờ có thể được áp dụng.
zerweck

68

Andy Lester đã đúng, nhưng nếu thư mục của bạn chỉ cần trống, và không trống rỗng, bạn có thể đặt một .gitignoretệp trống vào đó như một cách giải quyết.

Bên cạnh đó, đây là một vấn đề triển khai, không phải là vấn đề thiết kế lưu trữ Git cơ bản. Như đã được đề cập nhiều lần trong danh sách gửi thư của Git, lý do mà việc này chưa được thực hiện là vì không ai quan tâm đủ để gửi một bản vá cho nó, không phải là không thể hoặc không nên thực hiện.


4
Đó chính xác là những gì tôi nói. Cả hai đoạn được đề cập trong đoạn Câu hỏi thường gặp tôi đã đăng.
Andy Lester

1
Tôi nghĩ rằng một bên là thú vị và hữu ích để biết - nó có thể được sửa chữa, chỉ cần không mong đợi nó sớm bất cứ khi nào có một cách giải quyết dễ dàng như vậy cho hầu hết các trường hợp.
wnoise

Xin lỗi, tôi đã không đọc đoạn cuối cùng, và trong khi tôi đã đọc đoạn đầu tiên, tôi không chắc tại sao tôi lại lặp lại thông tin đó.
Aristotle Pagaltzis

2
Tất nhiên, câu trả lời thêm này không phục vụ để chỉ ra thực tế.
Michael Johnson

Tôi đã đến đây để xem xét một trường hợp bản dựng bị sụp đổ nếu thư mục không tồn tại và theo mặc định nó trống, nhưng nó không cần phải trống. Tạo một .gitignore làm điều đúng đắn.
Joshua

33

Cách tạo thư mục nhật ký Ruby on Rails :

mkdir log && touch log/.gitkeep && git add log/.gitkeep

Bây giờ thư mục log sẽ được bao gồm trong cây. Nó rất hữu ích khi triển khai, vì vậy bạn sẽ không phải viết một thói quen để tạo các thư mục nhật ký.

Các logfiles có thể được giữ bằng cách phát hành,

echo log/dev.log >> .gitignore

nhưng bạn có thể biết điều đó.


23
Điều đó có liên quan gì với Ruby on Rails?
Câu hỏi Quolonel


30

Git không theo dõi các thư mục trống. Xem Câu hỏi thường gặp về Git để được giải thích thêm. Cách giải quyết được đề xuất là đặt một .gitignoretệp trong thư mục trống. Tôi không thích giải pháp đó, vì.gitignore quy ước "bị ẩn" bởi Unix. Ngoài ra không có lời giải thích tại sao các thư mục trống.

Tôi đề nghị đặt một tệp README trong thư mục trống giải thích lý do tại sao thư mục trống và tại sao nó cần được theo dõi trong Git. Với tệp README đã có, theo như Git, thư mục không còn trống.

Câu hỏi thực sự là tại sao bạn cần thư mục trống trong git? Thông thường bạn có một số loại kịch bản xây dựng có thể tạo thư mục trống trước khi biên dịch / chạy. Nếu không thì làm một cái. Đó là một giải pháp tốt hơn nhiều so với việc đặt các thư mục trống trong git.

Vì vậy, bạn có một số lý do tại sao bạn cần một thư mục trống trong git. Đặt lý do đó trong tệp README. Bằng cách đó, các nhà phát triển khác (và tương lai bạn) biết tại sao thư mục trống cần phải ở đó. Bạn cũng sẽ biết rằng bạn có thể xóa thư mục trống khi vấn đề yêu cầu thư mục trống đã được giải quyết.


Để liệt kê mọi thư mục trống, sử dụng lệnh sau:

find -name .git -prune -o -type d -empty -print

Để tạo trình giữ chỗ READMEs trong mọi thư mục trống:

find -name .git -prune -o -type d -empty -exec sh -c \
  "echo this directory needs to be empty because reasons > {}/README.emptydir" \;

Để bỏ qua mọi thứ trong thư mục ngoại trừ tệp README, hãy đặt các dòng sau vào .gitignore :

path/to/emptydir/*
!path/to/emptydir/README.emptydir
path/to/otheremptydir/*
!path/to/otheremptydir/README.emptydir

Ngoài ra, bạn chỉ có thể loại trừ mọi tệp README khỏi bị bỏ qua:

path/to/emptydir/*
path/to/otheremptydir/*
!README.emptydir

Để liệt kê mọi README sau khi chúng được tạo:

find -name README.emptydir

28

CẢNH BÁO: Tinh chỉnh này không thực sự hoạt động khi nó bật ra. Xin lỗi vì sự bất tiện.

Bài gốc dưới đây:

Tôi tìm thấy một giải pháp trong khi chơi với Git internals!

  1. Giả sử bạn đang ở trong kho lưu trữ của bạn.
  2. Tạo thư mục trống của bạn:

    $ mkdir path/to/empty-folder
    
  3. Thêm nó vào chỉ mục bằng cách sử dụng lệnh hệ thống ống nước và cây trống SHA-1 :

    $ git update-index --index-info
    040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904    path/to/empty-folder
    

    Nhập lệnh và sau đó nhập dòng thứ hai. Nhấn Entervà sau đó Ctrl+ Dđể chấm dứt đầu vào của bạn. Lưu ý: định dạng là chế độ [SPACE] loại [SPACE] SHA-1hash [TAB] đường dẫn (tab rất quan trọng, định dạng câu trả lời không bảo tồn nó).

  4. Đó là nó! Thư mục trống của bạn là trong chỉ mục của bạn. Tất cả bạn phải làm là cam kết.

Giải pháp này ngắn và rõ ràng hoạt động tốt ( xem EDIT! ), Nhưng nó không dễ nhớ ...

Cây rỗng SHA-1 có thể được tìm thấy bằng cách tạo một kho Git trống mới, cdvào đó và phát hành git write-tree, cây này tạo ra cây rỗng SHA-1.

BIÊN TẬP:

Tôi đã sử dụng giải pháp này kể từ khi tôi tìm thấy nó. Nó dường như hoạt động chính xác giống như cách tạo một mô hình con, ngoại trừ việc không có mô-đun nào được xác định ở bất cứ đâu. Điều này dẫn đến lỗi khi ban hành git submodule init|update. Vấn đề là git update-indexviết lại 040000 treephần đó thành160000 commit .

Hơn nữa, bất kỳ tệp nào được đặt dưới đường dẫn đó sẽ không được Git chú ý, vì nó nghĩ rằng chúng thuộc về một số kho lưu trữ khác. Điều này là khó chịu vì nó có thể dễ dàng bị bỏ qua!

Tuy nhiên, nếu bạn chưa (và sẽ không) sử dụng bất kỳ mô hình con Git nào trong kho lưu trữ của mình và thư mục "trống" sẽ vẫn trống hoặc nếu bạn muốn Git biết về sự tồn tại của nó và bỏ qua nội dung của nó, bạn có thể đi cùng điều chỉnh này. Đi theo cách thông thường với các mô hình con mất nhiều bước hơn mà điều chỉnh này.


Sau khi đặt thư mục trống vào chỉ mục và cam kết, sau đó nó có thể git svn dcommitvới kết quả mong muốn không?
Chuộc tội có giới hạn

2
Không chắc là tinh chỉnh này sẽ hoạt động với bất kỳ công cụ nào khác. Giống như đã nêu trong cảnh báo và chỉnh sửa, tôi không khuyến khích sử dụng nó trừ khi trong trường hợp khá hạn chế.
ofavre

1
Và tất nhiên đây là lý do tại sao việc gây rối với nội bộ git bị chống chỉ định.
Casey

@abhisekp Làm thế nào mà thậm chí có thể?
PyRulez

1
@PyRulez tốt, trong thế giới phần mềm, không có gì là không thể. : D Thật ra, tôi đã làm theo câu trả lời.
abhisekp

21

Giả sử bạn cần một thư mục trống có tên tmp :

$ mkdir tmp
$ touch tmp/.gitignore
$ git add tmp
$ echo '*' > tmp/.gitignore
$ git commit -m 'Empty directory' tmp

Nói cách khác, bạn cần thêm tệp .gitignore vào chỉ mục trước khi bạn có thể nói với Git bỏ qua nó (và mọi thứ khác trong thư mục trống).


11
Hai điều: Bạn chỉ có thể "echo '*'> tmp / .gitignore" thay vì chạm và "git commit -m" không cam kết thay đổi được thực hiện sau khi bạn đã thêm các tệp vào chỉ mục.
Christoffer Hammarström

6
Nếu bạn chỉ làm echo bla > filebạn sẽ không nhận file: File exists>sẽ ghi đè lên các tập tin nếu nó đã có hoặc tạo một hình mới nếu nó không tồn tại.
psyrendust

3
/bin/shgiả định văn hóa! * Nếu "ở đây" là cshvà biến noclobberđược đặt, bạn thực sự sẽ nhận được file: File exists. Nếu ai đó nói "Tôi hiểu điều này", đừng cho rằng họ là một thằng ngốc và trả lời "Không, bạn không". * c2.com/cgi/wiki?AmericanCestationAsscharge
clacke

1
@clacke Nếu ai đó quyết định sử dụng shell khác với mọi người khác, họ nên nói rõ điều đó nếu họ gặp phải vấn đề. Không giống như quốc tịch, mọi người đều có sự lựa chọn miễn phí về vỏ.
Hiếm khi

2
@SeldomNeedy Có lẽ họ đang tìm kiếm sự giúp đỡ vì họ thậm chí không biết họ đang sử dụng một vỏ khác với mọi người khác.
clacke

20

Có thể việc thêm một thư mục trống có vẻ như đó sẽ là đường dẫn ít kháng cự nhất vì bạn có các tập lệnh mong muốn thư mục đó tồn tại (có thể vì đó là mục tiêu cho các nhị phân được tạo). Một cách tiếp cận khác là sửa đổi tập lệnh của bạn để tạo thư mục khi cần .

mkdir --parents .generated/bin ## create a folder for storing generated binaries
mv myprogram1 myprogram2 .generated/bin ## populate the directory as needed

Trong ví dụ này, bạn có thể kiểm tra một liên kết tượng trưng (bị hỏng) đến thư mục để bạn có thể truy cập nó mà không cần tiền tố ".generated" (nhưng đây là tùy chọn).

ln -sf .generated/bin bin
git add bin

Khi bạn muốn dọn sạch cây nguồn của mình, bạn có thể chỉ cần:

rm -rf .generated ## this should be in a "clean" script or in a makefile

Nếu bạn thực hiện phương pháp kiểm tra được đề xuất trong một thư mục gần như trống rỗng, bạn có một sự phức tạp nhỏ trong việc xóa nội dung mà không xóa tệp ".gitignore".

Bạn có thể bỏ qua tất cả các tệp được tạo bằng cách thêm phần sau vào gốc .gitignore:

.generated

1
Lưu ý: Liên kết tượng trưng mà tôi đề xuất là "bị hỏng" trong thanh toán sạch vì .generatedthư mục ban đầu không tồn tại. Nó sẽ không còn bị phá vỡ một khi bạn thực hiện việc xây dựng của mình.
tộc

2
Tôi đồng ý trong một số trường hợp đây là một ý tưởng rất tốt, nhưng trong những trường hợp khác (chẳng hạn như phân phối một dự án nơi bạn có bộ xương trống rỗng với các thư mục như mô hình / và khung nhìn /) bạn sẽ muốn người dùng có sẵn các thư mục này hơn là phải đọc các tài liệu theo cách thủ công, và có thể hơi nhiều để mong đợi họ chạy một số loại kịch bản cài đặt sau khi sao chép repo. Tôi nghĩ rằng câu trả lời này kết hợp với câu trả lời README của @ john-mee sẽ bao gồm hầu hết các trường hợp.
moopet

14

Tôi cũng đã phải đối mặt với vấn đề với các thư mục trống. Vấn đề với việc sử dụng tệp giữ chỗ là bạn cần tạo chúng và xóa chúng, nếu không cần thiết nữa (vì sau này có thêm thư mục con hoặc tệp. Với các cây nguồn lớn quản lý các tệp giữ chỗ này có thể bị cồng kềnh và lỗi dễ bị.

Đây là lý do tại sao tôi quyết định viết một công cụ nguồn mở có thể tự động quản lý việc tạo / xóa các tệp giữ chỗ như vậy. Nó được viết cho nền tảng .NET và chạy dưới Mono (.NET cho Linux) và Windows.

Chỉ cần xem tại: http://code.google.com.vn/p/markemptydirs


14

Tôi thích câu trả lời của @ Artur79 và @mjs vì vậy tôi đã sử dụng kết hợp cả hai và biến nó thành tiêu chuẩn cho các dự án của chúng tôi.

find . -type d -empty -exec touch {}/.gitkeep \;

Tuy nhiên, chỉ một số ít các nhà phát triển của chúng tôi làm việc trên Mac hoặc Linux. Rất nhiều công việc trên Windows và tôi không thể tìm thấy một lớp lót đơn giản tương đương để thực hiện tương tự ở đó. Một số người đã may mắn cài đặt Cygwin vì những lý do khác, nhưng việc kê đơn Cygwin chỉ vì điều này có vẻ quá mức cần thiết.

Chỉnh sửa để có giải pháp tốt hơn

Vì vậy, vì hầu hết các nhà phát triển của chúng tôi đã cài đặt Ant , điều đầu tiên tôi nghĩ đến là kết hợp một tệp xây dựng Ant để thực hiện việc này một cách độc lập với nền tảng. Điều này vẫn có thể được tìm thấy ở đây

Tuy nhiên , sau đó tôi nghĩ sẽ tốt hơn nếu biến nó thành một lệnh tiện ích nhỏ, vì vậy tôi đã tạo lại nó bằng Python và xuất bản nó lên PyPI tại đây . Bạn có thể cài đặt nó bằng cách chạy đơn giản:

pip3 install gitkeep2

Nó sẽ cho phép bạn tạo và xóa .gitkeepcác tệp đệ quy, và nó cũng sẽ cho phép bạn thêm tin nhắn cho chúng để các đồng nghiệp của bạn hiểu lý do tại sao các thư mục đó quan trọng. Bit cuối cùng này là tiền thưởng. Tôi nghĩ rằng nó sẽ được tốt đẹp nếu các .gitkeeptập tin có thể tự ghi lại.

$ gitkeep --help
Usage: gitkeep [OPTIONS] PATH

  Add a .gitkeep file to a directory in order to push them into a Git repo
  even if they're empty.

  Read more about why this is necessary at: https://git.wiki.kernel.org/inde
  x.php/Git_FAQ#Can_I_add_empty_directories.3F

Options:
  -r, --recursive     Add or remove the .gitkeep files recursively for all
                      sub-directories in the specified path.
  -l, --let-go        Remove the .gitkeep files from the specified path.
  -e, --empty         Create empty .gitkeep files. This will ignore any
                      message provided
  -m, --message TEXT  A message to be included in the .gitkeep file, ideally
                      used to explain why it's important to push the specified
                      directory to source control even if it's empty.
  -v, --verbose       Print out everything.
  --help              Show this message and exit.

Tôi hy vọng bạn thấy nó hữu dụng.


13

Bạn không thể và không may sẽ không bao giờ có thể. Đây là một quyết định được đưa ra bởi chính Linus Torvald. Anh ấy biết những gì tốt cho chúng ta.

Có một câu nói hay ở đâu đó tôi đã đọc một lần.

Tôi tìm thấy Re: rỗng thư mục .. , nhưng có lẽ có một thư mục khác.

Bạn phải sống với cách giải quyết ... thật không may.


1
Tôi biết bạn đã đăng bài này như một ví dụ về một đối số xấu, nhưng tôi đánh giá cao liên kết này vì đây thực sự là một lý lẽ hợp lý chống lại các thư mục theo dõi. ;-)
clacke

1
Câu trả lời này dường như không nhất quán, vì trong bài đăng tiếp theo về chủ đề được tham chiếu, Linus Torvald nói rằng ông hy vọng rằng họ sẽ cần thêm theo dõi thư mục: markmail.org/message/libip4vpvvxhyqbl . Trên thực tế, anh ta nói rằng anh ta "sẽ hoan nghênh các bản vá mà [thêm hỗ trợ để theo dõi các thư mục trống]"
Patrick M

Patrick, anh cũng dùng từ "ngốc" ở đó. Tôi nghi ngờ cách diễn đạt của anh ấy dành cho những người ở đây trong chủ đề này và vì vậy tôi cho rằng anh ấy sẽ không tự mình thực hiện một cái gì đó "ngu ngốc" vào Git.
user2334883

10

Khi bạn thêm một .gitignoretệp, nếu bạn định đặt bất kỳ lượng nội dung nào vào đó (mà bạn muốn Git bỏ qua), bạn có thể muốn thêm một dòng chỉ bằng dấu hoa thị *để đảm bảo bạn không vô tình thêm nội dung bị bỏ qua .


9

Không có cách nào để Git theo dõi các thư mục, vì vậy giải pháp duy nhất là thêm tệp giữ chỗ trong thư mục mà bạn muốn Git theo dõi.

Tệp có thể được đặt tên và chứa bất cứ thứ gì bạn muốn, nhưng hầu hết mọi người sử dụng một tệp trống có tên .gitkeep(mặc dù một số người thích thuyết bất khả tri của VCS .keep).

Tiền tố .đánh dấu nó là một tập tin ẩn.

Một ý tưởng khác là thêm một READMEtập tin giải thích thư mục sẽ được sử dụng cho mục đích gì.


8

Như đã đề cập, không thể thêm các thư mục trống, nhưng đây là một lớp lót thêm các tệp .gitignore trống vào tất cả các thư mục.

ruby -e 'require "fileutils" ; Dir.glob(["target_directory","target_directory/**"]).each { |f| FileUtils.touch(File.join(f, ".gitignore")) if File.directory?(f) }'

Tôi đã dán cái này vào Rakefile để dễ truy cập.


6
Tôi muốn sử dụngfind . -type d -empty -print0 | xargs --null bash -c 'for a; do { echo "*"; echo "!.gitignore"; } >>"$a/.gitignore"; done' --
Tino

8

Giải pháp của Jamie Flournoy hoạt động tuyệt vời. Đây là một phiên bản nâng cao một chút để giữ .htaccess:

# Ignore everything in this directory
*
# Except this file
!.gitignore
!.htaccess

Với giải pháp này, bạn có thể cam kết một thư mục trống, ví dụ /log, /tmphoặc /cachethư mục sẽ trống.


2
Anh ta muốn giữ một thư mục trống và không phải là một tập tin.
gvsrepins

2
Và tôi đã đề cập rằng nó cũng sẽ giữ .htaccess. Ví dụ: nếu một phần mềm có một thư mục cho các tệp nhật ký (như oxy eshop) không thể truy cập được qua web, thì có một .htaccess trong thư mục. Nếu bạn đặt .gitignore đã đề cập ở trên vào thư mục, .htaccess sẽ không được gửi và thư mục sẽ có thể truy cập qua web.
La Mã

Nếu bạn có tệp .htaccess nằm dưới sự kiểm soát phiên bản, thì bạn đã có thư mục chứa tệp đó dưới sự kiểm soát phiên bản. Do đó, vấn đề đã được giải quyết - tệp .gitignore trở nên không liên quan.
Ponkadoodle

1
@Wallacoloo Liên quan đến câu hỏi bạn đúng, tuy nhiên tệp rất hữu ích, tôi sẽ sử dụng nó cho một thư mục tải lên giống như nơi các tệp sẽ được bảo vệ bởi .htaccess. Trái với giải thích của người La Mã, tệp .htaccess sẽ được cam kết vì nó bị loại trừ bởi quy tắc bỏ qua. [chủ đề cũ, tôi biết]
David

7

Tôi luôn xây dựng một chức năng để kiểm tra cấu trúc thư mục mong muốn của mình và xây dựng nó cho tôi trong dự án. Điều này giải quyết vấn đề này vì các thư mục trống được giữ trong Git bằng proxy.

function check_page_custom_folder_structure () {
    if (!is_dir(TEMPLATEPATH."/page-customs"))
        mkdir(TEMPLATEPATH."/page-customs");    
    if (!is_dir(TEMPLATEPATH."/page-customs/css"))
        mkdir(TEMPLATEPATH."/page-customs/css");
    if (!is_dir(TEMPLATEPATH."/page-customs/js"))
        mkdir(TEMPLATEPATH."/page-customs/js");
}

Đây là trong PHP, nhưng tôi chắc chắn rằng hầu hết các ngôn ngữ đều hỗ trợ cùng chức năng và vì việc tạo các thư mục được ứng dụng chăm sóc, các thư mục sẽ luôn ở đó.


2
Chỉ để tất cả chúng ta trên cùng một trang, tôi không làm điều này nữa. Thật là phí thời gian. Các .gitkeepquy ước là một thực hành tốt hơn nhiều.
Fuzz nhẹ

Tôi không thể thấy làm thế nào điều này có thể lãng phí thời gian. Khi TEMPLATEPATH của bạn rõ ràng là động, bạn không thể sử dụng giải pháp .gitkeep. Và ngay cả với cấu trúc thư mục không liên kết, bạn nên thêm một số nội dung khác thay vì xóa giải pháp kiểm tra thư mục rất tốt, ví dụ: kiểm tra quyền và kiểm tra các tệp. Thêm một cách để đánh dấu các thư mục bên trong .gitignore toàn cầu sẽ là hoàn hảo đối với tôi. Một cái gì đó như #keep / path / to / dir
Jochen Schultz

7

Đây là một bản hack, nhưng thật buồn cười là nó hoạt động (Git 2.2.1). Tương tự như những gì @Teka đề xuất, nhưng dễ nhớ hơn:

  • Thêm một mô hình con vào bất kỳ kho lưu trữ ( git submodule add path_to_repo)
  • Điều này sẽ thêm một thư mục và một tập tin .submodules. Cam kết thay đổi.
  • Xóa .submodulestập tin và cam kết thay đổi.

Bây giờ, bạn có một thư mục được tạo khi kiểm tra cam kết. Mặc dù vậy, một điều thú vị là nếu bạn nhìn vào nội dung của đối tượng cây của tệp này, bạn sẽ nhận được:

gây tử vong: Không phải là một tên đối tượng hợp lệ b64338b90b4209263b50244d18278c0999867193

Tôi sẽ không khuyến khích sử dụng nó mặc dù nó có thể ngừng hoạt động trong các phiên bản tương lai của Git. Mà có thể để kho lưu trữ của bạn bị hỏng.


Điều này thực sự hoạt động nhưng tôi nghĩ nhầm lẫn giữa IntelliJ ...: |
rogerdpack

Tôi đã tạo ra một giải pháp tốt hơn dựa trên giải pháp không có nhược điểm này: stackoverflow.com/a/58543445/277882
ntninja

7

Nhiều người đã trả lời câu hỏi này. Chỉ cần thêm phiên bản PowerShell tại đây.

Tìm tất cả các thư mục trống trong thư mục

Thêm một tập tin .gitkeep trống trong đó

Get-ChildItem 'Path to your Folder' -Recurse -Directory | Where-Object {[System.IO.Directory]::GetFileSystemEntries($_.FullName).Count -eq 0} | ForEach-Object { New-Item ($_.FullName + "\.gitkeep") -ItemType file}

Nice. (͡☉ ͜ʖ ͡☉)
FiringSquadWitness

6

Nếu bạn muốn thêm một thư mục chứa nhiều dữ liệu nhất thời trong nhiều thư mục ngữ nghĩa, thì một cách tiếp cận là thêm một cái gì đó như thế này vào thư mục gốc của bạn .gitignore ...

/app/data/**/*.* !/app/data/**/*.md

Sau đó, bạn có thể cam kết các tệp README.md mô tả (hoặc các tệp trống, không quan trọng, miễn là bạn có thể nhắm mục tiêu chúng duy nhất giống như *.mdtrong trường hợp này) trong mỗi thư mục để đảm bảo rằng tất cả các thư mục vẫn là một phần của repo nhưng các tập tin (có phần mở rộng) được giữ lại bỏ qua. GIỚI HẠN:. Không được phép trong tên thư mục!

Bạn có thể điền vào tất cả các thư mục này bằng các tệp xml / hình ảnh hoặc bất cứ thứ gì và thêm nhiều thư mục bên dưới /app/data/ thời gian khi nhu cầu lưu trữ cho ứng dụng của bạn phát triển (với các tệp README.md phục vụ để ghi trong mô tả về mỗi thư mục lưu trữ dành cho chính xác).

Không cần phải thay đổi thêm .gitignorehoặc phân cấp của bạn bằng cách tạo một cái mới .gitignorecho mỗi thư mục mới. Có lẽ không phải là giải pháp thông minh nhất nhưng lại rất khôn ngoan và luôn làm việc cho tôi. Đẹp và đơn giản! ;)

nhập mô tả hình ảnh ở đây


6

Một cách dễ dàng để làm điều này là bằng cách thêm một .gitkeeptệp vào thư mục bạn muốn (hiện tại) để trống.

Xem câu trả lời SOF này để biết thêm thông tin - cũng giải thích lý do tại sao một số người tìm thấy quy ước cạnh tranh của việc thêm tệp .gitignore (như đã nêu trong nhiều câu trả lời ở đây) gây nhầm lẫn.


4

Thêm một lựa chọn nữa vào cuộc cạnh tranh.

Giả sử bạn muốn thêm một thư mục vào gitđó, cho tất cả các mục đích liên quan đến git, nên để trống và không bao giờ để nội dung của nó được theo dõi, .gitignorenhư được đề xuất nhiều lần ở đây, sẽ thực hiện thủ thuật.

Định dạng, như đã đề cập, là:

*
!.gitignore

Bây giờ, nếu bạn muốn một cách để làm điều này tại dòng lệnh, trong một cú trượt, trong khi bên trong thư mục bạn muốn thêm, bạn có thể thực thi:

$ echo "*" > .gitignore && echo '!.gitignore' >> .gitignore && git add .gitignore

Chính tôi, tôi có một kịch bản shell mà tôi sử dụng để làm điều này. Đặt tên cho kịch bản bất cứ điều gì bạn muốn, và thêm nó vào đâu đó trong đường dẫn bao gồm của bạn hoặc tham chiếu trực tiếp:

#!/bin/bash

dir=''

if [ "$1" != "" ]; then
    dir="$1/"
fi

echo "*" > $dir.gitignore && \
echo '!.gitignore' >> $dir.gitignore && \
git add $dir.gitignore

Với điều này, bạn có thể thực thi nó từ trong thư mục bạn muốn thêm hoặc tham chiếu thư mục là tham số đầu tiên và duy nhất:

$ ignore_dir ./some/directory

Một tùy chọn khác (để đáp lại một lời nhận xét của @GreenAsJade), nếu bạn muốn theo dõi một thư mục trống mà THÁNG chứa các file được theo dõi trong tương lai, nhưng sẽ trống cho bây giờ, bạn có thể ommit *từ .gitignoretập tin, và kiểm tra rằng trong. Về cơ bản, tất cả các tập tin đang nói là "đừng bỏ qua tôi ", nhưng nếu không, thư mục trống và được theo dõi.

Tệp của bạn .gitignoresẽ trông như sau:

!.gitignore

Đó là nó, kiểm tra xem, và bạn có một thư mục trống, chưa được theo dõi, mà bạn có thể theo dõi các tệp vào một lúc nào đó.

Lý do tôi khuyên bạn nên giữ một dòng trong tệp là vì nó mang lại .gitignoremục đích. Nếu không, một số người xuống dòng có thể nghĩ để loại bỏ nó. Nó có thể giúp nếu bạn đặt một bình luận trên dòng.


4

Đôi khi bạn phải đối phó với các thư viện hoặc phần mềm bị viết xấu, cần một thư mục trống và thực "thực". Đặt một đơn giản .gitignorehoặc .keepcó thể phá vỡ chúng và gây ra lỗi. Những điều sau đây có thể giúp ích trong những trường hợp này, nhưng không có gì đảm bảo ...

Đầu tiên tạo thư mục cần thiết:

mkdir empty

Sau đó, bạn thêm một liên kết tượng trưng bị hỏng vào thư mục này (nhưng trong bất kỳ trường hợp nào khác ngoài trường hợp sử dụng được mô tả ở trên, vui lòng sử dụng một READMElời giải thích):

ln -s .this.directory empty/.keep

Để bỏ qua các tập tin trong thư mục này, bạn có thể thêm nó trong thư mục gốc của bạn .gitignore:

echo "/empty" >> .gitignore

Để thêm tệp bị bỏ qua, sử dụng một tham số để buộc nó:

git add -f empty/.keep

Sau khi xác nhận, bạn có một liên kết tượng trưng bị hỏng trong chỉ mục của bạn và git tạo thư mục. Liên kết bị hỏng có một số lợi thế, vì nó không phải là tệp thông thường và trỏ đến không có tệp thông thường. Vì vậy, nó thậm chí phù hợp với một phần của câu hỏi "(không chứa tệp)", không phải bởi ý định mà bởi ý nghĩa, tôi đoán:

find empty -type f

Lệnh này hiển thị một kết quả trống, vì không có tệp nào trong thư mục này. Vì vậy, hầu hết các ứng dụng nhận được tất cả các tệp trong một thư mục thường không thấy liên kết này, ít nhất là nếu chúng thực hiện "tệp tồn tại" hoặc "có thể đọc được". Thậm chí một số tập lệnh sẽ không tìm thấy bất kỳ tập tin nào ở đó:

$ php -r "var_export(glob('empty/.*'));"
array (
  0 => 'empty/.',
  1 => 'empty/..',
)

Nhưng tôi thực sự khuyên bạn chỉ nên sử dụng giải pháp này trong những trường hợp đặc biệt, một bài viết hay READMEtrong một thư mục trống thường là một giải pháp tốt hơn. (Và tôi không biết điều này có hoạt động với hệ thống tập tin windows không ...)


4

Đọc câu trả lời của @ofavre@ stanislav-bashkyrtsev bằng cách sử dụng các tham chiếu mô hình con GIT bị hỏng để tạo các thư mục GIT, tôi ngạc nhiên rằng không ai đề xuất sửa đổi ý tưởng đơn giản này để làm cho toàn bộ điều này an toàn và an toàn:

Thay vì hack một mô hình con giả vào GIT , chỉ cần thêm một thực tế trống .

Nhập: https://gitlab.com/empty-repo/empty.git

Kho lưu trữ GIT với chính xác một cam kết:

commit e84d7b81f0033399e325b8037ed2b801a5c994e0
Author: Nobody <none>
Date: Thu Jan 1 00:00:00 1970 +0000

Không có tin nhắn, không có tập tin cam kết.

Sử dụng

Để thêm một thư mục trống cho bạn repo GIT:

git submodule add https://gitlab.com/empty-repo/empty.git path/to/dir

Để chuyển đổi tất cả các thư mục trống hiện có sang mô hình con:

find . -type d -empty -delete -exec git submodule add -f https://gitlab.com/empty-repo/empty.git \{\} \;

Git sẽ lưu trữ hàm băm cam kết mới nhất khi tạo tham chiếu mô hình con, vì vậy bạn không phải lo lắng về tôi (hoặc GitLab) khi sử dụng tệp này để tiêm các tệp độc hại. Thật không may, tôi không tìm thấy bất kỳ cách nào để buộc ID cam kết nào được sử dụng trong quá trình thanh toán, vì vậy bạn sẽ phải kiểm tra thủ công ID cam kết tham chiếu đang e84d7b81f0033399e325b8037ed2b801a5c994e0sử dụng git submodule statussau khi thêm repo.

Vẫn không phải là một giải pháp bản địa, nhưng điều tốt nhất chúng ta có thể có mà không cần ai đó có được bàn tay của họ thực sự , thực sự bẩn trong cơ sở mã GIT.

Phụ lục: Tái tạo cam kết này

Bạn sẽ có thể tạo lại cam kết chính xác này bằng cách sử dụng (trong một thư mục trống):

# Initialize new GIT repository
git init

# Set author data (don't set it as part of the `git commit` command or your default data will be stored as “commit author”)
git config --local user.name "Nobody"
git config --local user.email "none"

# Set both the commit and the author date to the start of the Unix epoch (this cannot be done using `git commit` directly)
export GIT_AUTHOR_DATE="Thu Jan 1 00:00:00 1970 +0000"
export GIT_COMMITTER_DATE="Thu Jan 1 00:00:00 1970 +0000"

# Add root commit
git commit --allow-empty --allow-empty-message --no-edit

Tạo các cam kết GIT có thể lặp lại là khó khăn đáng kinh ngạc


3

Bạn không thể. Đây là một quyết định thiết kế có chủ ý của những người bảo trì Git. Về cơ bản, mục đích của Hệ thống quản lý mã nguồn như Git là quản lý mã nguồn và các thư mục trống không phải là mã nguồn. Git cũng thường được mô tả như một trình theo dõi nội dung và một lần nữa, các thư mục trống không có nội dung (thực tế hoàn toàn ngược lại), vì vậy chúng không được theo dõi.


60
Tôi tranh luận về quan điểm này. Cấu trúc là nội dung và mọi thứ bạn đặt tên đều đóng góp cho nội dung.
ThomasH

20
Một tập tin trống không phải là mã nguồn hoặc nội dung. Đó chỉ là một cái tên. Tuy nhiên, Git sẽ vui vẻ theo dõi các tập tin trống. Tôi không nghĩ rằng đó là một quyết định thiết kế có chủ ý để khiến Git từ chối theo dõi các thư mục trống. Tôi nghĩ rằng theo dõi các thư mục trống là một tính năng đơn giản là không cần đến 99% thời gian, vì vậy họ không bận tâm làm thêm công việc cần thiết để làm cho nó hoạt động chính xác. Git có thể làm điều đó nếu ai đó muốn tính năng này đủ tệ để thực hiện nó. Tôi nghi ngờ những người duy trì Git sẽ phản đối một bản vá như vậy nếu nó được thực hiện đúng.
Dan Mould

1
@TobyAllen ở đây là liên kết Câu hỏi thường gặp được cập nhật Câu trả lời hàng đầu cũng là những gì được Câu hỏi thường gặp khuyến nghị với các hướng dẫn chính xác hơn.
Daniel Da Cunha

3
Đó là một tính năng bị thiếu (và mức độ ưu tiên thấp), không phải là giới hạn có chủ ý. Từ Câu hỏi thường gặp về Git: Hiện tại thiết kế chỉ mục Git (khu vực tổ chức) chỉ cho phép các tệp được liệt kê và không ai đủ thẩm quyền để thực hiện thay đổi để cho phép các thư mục trống đã quan tâm đủ về tình huống này để khắc phục.
jbo5112

Đừng thực sự đồng ý. Tôi có thể tìm thấy nhiều lý do tại sao tôi muốn theo dõi một thư mục trống. Ví dụ, tôi đang phát triển một khung công tác PHP MVC rất nhẹ cho các dự án của mình. Tôi có các thư mục cụ thể để đặt mô hình, chế độ xem, v.v. Khi tôi tạo một trang web mới dựa trên khung của mình, các thư mục đó trống vì không có mô hình hoặc chế độ xem theo mặc định, nhưng tôi cần thư mục tồn tại, nếu không thì khung của tôi đã thắng không hoạt động
Gladen

2

Bạn có thể lưu mã này dưới dạng create_readme.php và chạy mã PHP từ thư mục gốc của dự án Git của bạn.

> php create_readme.php

Nó sẽ thêm các tệp README vào tất cả các thư mục trống để các thư mục đó sau đó sẽ được thêm vào chỉ mục.

<?php
    $path = realpath('.');
    $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path),       RecursiveIteratorIterator::SELF_FIRST);
    foreach($objects as $name => $object){
        if ( is_dir($name) && ! is_empty_folder($name) ){
            echo "$name\n" ;
            exec("touch ".$name."/"."README");
        }
    }

    function is_empty_folder($folder) {
        $files = opendir($folder);
        while ($file = readdir($files)) {
            if ($file != '.' && $file != '..')
                return true; // Not empty
            }
        }
?>

Sau đó làm

git commit -m "message"
git push
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.