2014-05-09 19 views
6

Hầu như tất cả các dự án mà tôi đã thực hiện có một số loại "nội dung cố định" luôn phải đến khi được sao chép, nhưng hiếm khi được thay đổi (xem ví dụ bên dưới). Tôi đã thử các cách tiếp cận khác nhau bằng cách sử dụng git, nhưng tất cả đều dễ bị lỗi: mọi người thường xuyên vô tình thực hiện các thay đổi.git - xử lý nội dung cố định

Đó là một trường hợp tinh tế để đảm bảo: các tệp/thư mục phải được phiên bản, nhưng lớn nhất phần lớn các thay đổi sẽ không được đẩy.

Nhìn xung quanh tôi có một vài lựa chọn:

  • git update-index --assume-unchanged <file>: Vấn đề-would appear to be a local setting này, vì vậy đây chỉ giải quyết vấn đề trên một máy nhất định. Những bản sao mới dễ bị quên đi và vẫn vô tình thay đổi.
  • git update-index --skip-worktree <file>: Sự cố - Xuất hiện cùng một vấn đề, vì tôi không nghĩ rằng thay đổi đối với chỉ mục này được khuyến khích.
  • git rm --cached <file>: Vấn đề - không thực sự là giải pháp vì tất cả mọi người đều có bản sao của mọi người khi được đẩy!
  • echo <file> >> .gitignore: Sự cố - không thực sự là giải pháp vì điều này chỉ kiểm soát liệu đối tượng có được thêm vào repo hay không.
  • sử dụng bộ lọc làm sạch/loại trừ để loại trừ các thay đổi của tệp khỏi cam kết (xem answer) của jthill: Sự cố - phức tạp, dễ bị lỗi: vẫn cần mỗi trình phát để cấu hình cục bộ.

Câu trả lời có thể chấp nhận cho câu hỏi này không yêu cầu hành động đặc biệt của từng nhà phát triển mới.

Tại sao? Bởi vì đây chính xác là vấn đề với các giải pháp trên, trong đó, trong kinh nghiệm của tôi dẫn đến các tình huống mà "ai đó đã cam kết tập tin đó một lần nữa".

Tìm kiếm dễ dàng trả về nhiều câu hỏi. Chúng tôi cần câu trả lời cuối cùng!

Ví dụ:

Đây là trường hợp tôi giao dịch với máy ATM. Dự án của tôi là một trang web nhúng phần mềm wiki (mà tôi không viết). Thành phần wiki cần cấu trúc thư mục không tầm thường được sử dụng chứ không phải cơ sở dữ liệu (có thể là một cơ sở dữ liệu). Nó cần phải tìm các thư mục và các tập tin đã có để làm việc. Sau một thời gian các tệp này trở nên lớn - chúng tôi không muốn theo dõi những thay đổi đó! Cấu trúc thư mục này cũng chứa một số cấu hình (tôi biết).Nếu tôi có thể bao gồm bản sao trần trong repo, và bằng cách nào đó (hầu như) không bao giờ theo dõi những thay đổi của nó, đó sẽ là hoàn hảo.

+1

Bạn có thể cung cấp thêm một số chi tiết về "nội dung cố định" có thể là gì không? Bạn đang nói về các tập tin cấu hình? Cơ sở dữ liệu đồ đạc? Thứ gì khác? – Chris

+1

Câu hỏi hay (và nỗ lực nghiên cứu tốt). Đây thực sự là một câu hỏi thường gặp về Git và xứng đáng là một câu trả lời kinh điển. – sleske

+0

@Chris - đã thêm một số mô tả về các thư mục/tệp. –

Trả lời

3

Không thực sự rõ ràng loại tệp bạn đang nói đến.

Trong trường hợp các tập tin cấu hình, tôi luôn khuyên các phương pháp sau đây:

  1. Commit một tập tin cấu hình mẫu với giá trị mặc định lành mạnh, ví dụ config.sample.ini.
  2. Bỏ qua tệp không phải mẫu, ví dụ: config.ini.
  3. Là một phần của quy trình "khởi động" trên máy mới, tệp config.sample.ini phải được sao chép sang config.ini và tùy chỉnh. Ghi lại quá trình này trong README của bạn, hoặc wiki, hoặc bất cứ nơi nào.
  4. Đảm bảo mã của bạn "không đúng" nếu thiếu tệp cấu hình, ví dụ: khi phần mềm bắt đầu nó sẽ ngay lập tức lỗi với "Không thể tìm thấy config.ini. Bạn đã sao chép các tập tin mẫu?"

Điều này đảm bảo rằng tệp mẫu có thể được cập nhật dễ dàng. Nó đảm bảo rằng tập tin cấu hình không được cam kết. Nó thất bại một cách nhanh chóng nếu nó được thực hiện sai. Và nó tương đối đơn giản để thực hiện.

Cách nhanh nhất để nhận được từ một cam kết config.ini một lờ config.ini và một cam kết config.sample.ini có khả năng để làm một cái gì đó giống như

git mv config.ini config.sample.ini 
echo config.ini >> .gitignore 
git commit -a -m "Replace config file with sample config file" 

Cập nhật:

dụ wiki của bạn là một trong những thú vị.

Bạn nói đúng rằng một cây sâu sắc về .sample file sẽ rất khó để quản lý, nhưng bạn có thể có được tác dụng tương tự với một file zip hoặc tarball:

  1. Tạo một kho lưu trữ sẽ được cam kết kho chứa nội dung wiki cơ sở của bạn, ví dụ wiki.zip.
  2. Bỏ qua thư mục chứa wiki sẽ được trích xuất, ví dụ: path/to/wiki-root.
  3. Thêm "trích xuất wiki với unzip -d path/to/wiki-root" vào tài liệu của bạn. Đây là một phần của thủ tục cài đặt/triển khai của bạn.

Bây giờ bạn có thể cập nhật tệp zip nếu cần và cam kết những thay đổi đó, trong khi bỏ qua các thay đổi đối với tệp được trích xuất.

+0

Vâng, đó là cách tôi luôn thấy nó hoàn thành. Vấn đề của OP thực sự là một tệp đang phục vụ hai vai trò: mẫu cấu hình và tệp cấu hình. Có các tệp riêng biệt là giải pháp sạch nhất. – sleske

+0

Tôi thích cách tiếp cận đó. Hãy xem ví dụ tôi đã thêm vào cuối câu hỏi của mình (đây là những gì tôi thực sự đang gặp phải). Có lẽ tôi có thể sao chép toàn bộ cấu trúc thư mục dưới dạng mẫu, nhưng điều đó có vẻ quá mức. –

+0

@EdwardNewell vui lòng xem câu trả lời cập nhật của tôi. – Chris

3

AFAIK, cách duy nhất để thực thi chính sách "không thay đổi điều này" mà không có hành động tự nguyện trong mỗi bản sao của repo là cài đặt server-side hook cho họ. Một hook nhận trước có thể kiểm tra các cam kết đến cho các thay đổi đối với một tập tin bị đóng băng và từ chối chúng (trừ khi thông điệp commit khớp với một số mẫu ma thuật mà nó làm cho nó vượt qua).

Móc phía máy chủ chỉ hoạt động khi bạn kiểm soát repo trung tâm, tức là nó không thể trên GitHub hoặc một số dịch vụ như vậy.

+0

Ah, một sự nhỡ gần. Nó quá tệ, chúng tôi không thể sử dụng nó cho github. Tuy nhiên, điều này sẽ giúp ích nhiều. –

1

Đặt các tập tin sau đây trong dự án của bạn như <proj-root>/.git/hooks/pre-commit

#!/bin/sh 

numFilesToVerify=0 
IFS=$'\n' 

for l in `git diff --name-only --cached`; do 
    while read m; do 
     [[ $l == $m ]] && verify="$verify"`echo " * $l"`$'\n' && ((numFilesToVerify++)) 
    done < .gitverify 
done 

if [ $numFilesToVerify -gt 0 ]; then 
    echo "\nYou're changing $numFilesToVerify frozen files:"; 
    echo "$verify" 
    read -p "Do you know what you're doing? (yes/no): " reply < /dev/tty 
    if [ "$reply" != "yes" ]; then 
     echo 'commit aborted.' 
     exit 1; 
    fi 
fi 

unset IFS 

Sau đó, danh sách các tập tin hoặc thư mục bạn muốn đóng băng trong file <proj-root>/.gitverify. Sử dụng * wildcard nếu bạn muốn:

testdir/test* 

Đây là những gì sẽ xảy ra nếu tôi cố gắng để thực hiện thay đổi đối với file tesdir/testtestdir/test2

$ git commit -m 'test' 
You're changing 2 frozen files: 
* testdir/test 
* testdir/test2 

Do you know what you're doing? (yes/no): no 
commit aborted. 

Ưu điểm:

  • tôi có thể dễ dàng thêm/xóa các tệp khỏi danh sách đóng băng
  • Nếu cập nhật một phần của tar (xem câu trả lời của Chris), một tệp dễ bị ghi đè lên một phần không t dự định được thay đổi. Không có tars cần thiết ở đây, và nó cho bạn biết những gì có khả năng điều ngu ngốc bạn đang làm.
  • không sử dụng móc phía máy chủ, do đó không có vấn đề gì khi truy cập hoặc có nhiều điều khiển từ xa.
+1

Đây là một giải pháp thú vị, nhưng không vi phạm câu hỏi "Câu trả lời có thể chấp nhận cho câu hỏi này không yêu cầu hành động đặc biệt của mỗi nhà phát triển mới"? Tôi khá chắc chắn rằng mỗi người dùng sẽ phải thiết lập móc này bằng tay sau khi nhân bản, vì móc không phải là một phần của kho lưu trữ. – Chris

+0

@Chris darn! Tôi cho là như vậy. –

Các vấn đề liên quan