Chuyển từ CVS sang Git: $ Id $ tương đương?


124

Tôi đã đọc qua một loạt các câu hỏi hỏi về các công cụ kiểm soát mã nguồn đơn giản và Git dường như là một lựa chọn hợp lý. Tôi có nó và chạy, và nó hoạt động tốt cho đến nay. Một khía cạnh mà tôi thích về CVS là sự gia tăng tự động của số phiên bản.

Tôi hiểu rằng điều này có ý nghĩa ít hơn trong một kho lưu trữ phân tán, nhưng là một nhà phát triển, tôi muốn / cần một cái gì đó như thế này. Hãy để tôi giải thích tại sao:

Tôi sử dụng Emacs. Định kỳ tôi đi qua và tìm kiếm các phiên bản mới của tệp nguồn Lisp cho các gói của bên thứ ba. Giả sử tôi đã có một tệp, foo.el, theo tiêu đề, là phiên bản 1.3; Nếu tôi tra cứu phiên bản mới nhất và thấy nó là 1.143 hoặc 2.6 hoặc bất cứ điều gì, tôi biết tôi còn ở phía sau khá xa.

Thay vào đó, nếu tôi thấy một vài băm 40 ký tự, tôi sẽ không biết cái nào muộn hơn hoặc có ý tưởng nào về việc nó sẽ muộn hơn bao nhiêu. Tôi hoàn toàn ghét nó nếu tôi phải kiểm tra ChangeLogs theo cách thủ công chỉ để biết được tôi đã hết hạn như thế nào.

Là một nhà phát triển, tôi muốn mở rộng phép lịch sự này, như tôi thấy, với những người sử dụng đầu ra của tôi (và có lẽ tôi đang tự đùa với mình rằng bất cứ ai cũng vậy, nhưng hãy để chuyện đó sang một bên). Tôi không muốn phải nhớ tăng số lượng chết tiệt mỗi lần, hoặc dấu thời gian hoặc đại loại như thế. Đó là một PITA thực sự, và tôi biết điều đó từ kinh nghiệm.

Vậy tôi có những lựa chọn thay thế nào? Nếu tôi không thể nhận được $ Id: $ tương đương, làm thế nào khác tôi có thể cung cấp những gì tôi đang tìm kiếm?

Tôi nên đề cập rằng kỳ vọng của tôi là người dùng cuối sẽ KHÔNG cài đặt Git và ngay cả khi họ làm như vậy, sẽ không có kho lưu trữ cục bộ (thực sự, tôi hy vọng sẽ không cung cấp theo cách đó).

Câu trả lời:


67

SHA chỉ là một đại diện của một phiên bản (mặc dù kinh điển). Các git describelệnh cung cấp khác và làm như vậy khá tốt.

Ví dụ, khi tôi chạy git describetrong nhánh chính của nguồn máy khách memcached Java của mình , tôi nhận được điều này:

2.2-16-gc0cd61a

Điều đó nói lên hai điều quan trọng:

  1. Đã có chính xác 16 cam kết trong cây này kể từ 2.2
  2. Cây nguồn chính xác có thể được hiển thị trên bản sao của bất kỳ ai khác.

Ví dụ, giả sử bạn đã đóng gói một versiontệp có nguồn (hoặc thậm chí viết lại tất cả nội dung để phân phối) để hiển thị số đó. Hãy nói rằng phiên bản đóng gói là 2.2-12-g6c4ae7a(không phải là một phiên bản, nhưng là một phiên bản hợp lệ).

Bây giờ bạn có thể thấy chính xác khoảng cách phía sau của bạn (4 lần xác nhận) bạn có thể thấy chính xác 4 lần cam kết:

# The RHS of the .. can be origin/master or empty, or whatever you want.
% git log --pretty=format:"%h %an %s" 2.2-12-g6c4ae7a..2.2-16-gc0cd61a
c0cd61a Dustin Sallings More tries to get a timeout.
8c489ff Dustin Sallings Made the timeout test run on every protocol on every bui
fb326d5 Dustin Sallings Added a test for bug 35.
fba04e9 Valeri Felberg Support passing an expiration date into CAS operations.

1
Sử dụng điều này sẽ thất bại khi bạn hợp nhất nhánh phát triển, trong khi bản gốc có một số hotfix. Số lượng cam kết kể từ phiên bản cuối cùng sẽ thay đổi. Băm không đáng tin cậy vì ai đó có thể xây dựng lại toàn bộ với filter-branchhoặc một cái gì đó.
LeMike

Bài viết chỉ mô tả việc học thông tin, không nhúng nó vào thực thi của bạn. Vì vậy, bạn cần chạy git describelệnh ngay trước khi xây dựng, lưu kết quả đầu ra trong tệp tiêu đề hoặc nếu không thì nhúng giá trị vào mã của bạn.
Jesse Chisholm

55

Đến bây giờ đã có hỗ trợ cho $ Id: $ in Git. Để kích hoạt nó cho tệp README, bạn sẽ đặt "README nhận dạng" vào .gitattribut . Ký tự đại diện trên tên tập tin được hỗ trợ. Xem người đàn ông gitattote để biết chi tiết.


14
Điều này cung cấp cho bạn sha1 của blob, nhưng không phải là sha1 của cam kết. Hữu ích, không phải là một định danh cho cam kết.
Stephen Jennings

4
git không có bất kỳ cơ chế mở rộng từ khóa như $Id$đã đề cập. Những gì được lưu trữ đi chính xác là những gì bạn nhận được. Trong mọi trường hợp, phiên bản thuộc về bộ sưu tập đầy đủ các tệp tạo thành một cam kết, không phải là một tệp cụ thể (Ý tưởng đó là phần còn lại từ thời RCS, hoặc có lẽ SCCS sẽ đổ lỗi tại đây ... Vì CVS chỉ là một giao diện được tôn vinh cho RCS và SVN cố gắng trở thành một CVS giống như công việc, nó bị mắc kẹt.).
vonbrand

32

Đây không phải là một yêu cầu vô lý từ OP.

Trường hợp sử dụng của tôi là:

  1. Tôi sử dụng Git cho mã cá nhân của riêng tôi, do đó không hợp tác với người khác.
  2. Tôi giữ các tập lệnh Bash hệ thống trong đó có thể đi vào /usr/local/binkhi chúng sẵn sàng.

Tôi sử dụng ba máy riêng biệt với cùng một kho Git trên đó. Thật tuyệt khi biết "phiên bản" của tệp mà tôi hiện đang /usr/local/binsử dụng mà không phải thực hiện thủ công "diff -u <repo phiên bản> <phiên bản trong / usr / local / bin>".

Đối với những người tiêu cực, hãy nhớ có những trường hợp sử dụng khác ngoài kia. Không phải ai cũng sử dụng Git cho công việc cộng tác với các tệp trong kho Git là vị trí "cuối cùng" của họ.

Dù sao, cách tôi đã làm là tạo một tệp thuộc tính trong kho lưu trữ như thế này:

cat .git/info/attributes
# see man gitattributes
*.sh ident
*.pl ident
*.cgi ident

Sau đó đặt $ Id $ ở đâu đó trong tệp (tôi muốn đặt nó sau shebang).

Các cam kết. Lưu ý rằng điều này không tự động thực hiện việc mở rộng như tôi mong đợi. Bạn phải đồng lại tập tin, ví dụ,

git commit foo.sh
rm foo.sh
git co foo.sh

Và sau đó bạn sẽ thấy bản mở rộng, ví dụ:

$ head foo.sh
#!/bin/sh

# $Id: e184834e6757aac77fd0f71344934b1cd774e6d4 $

Một số thông tin tốt có trong Làm cách nào để kích hoạt chuỗi nhận dạng cho kho lưu trữ Git? .


3
Cần lưu ý rằng điều này không xác định (các blob) của tập tin hiện tại , chứ không phải cam kết hiện tại
CharlesB

3
Phải git colàm gì đây? Tôi nhận được thông báo lỗi " git: 'co' is not a git command. See 'git --help'." nên nó đượcgit checkout ?
Peter Mortensen

23

Không chắc chắn điều này sẽ bao giờ trong Git. Để trích dẫn Linus :

"Toàn bộ khái niệm thay thế từ khóa chỉ là hoàn toàn ngu ngốc. Thật là tầm thường khi thực hiện" bên ngoài "theo dõi nội dung thực tế, nếu bạn muốn có nó khi thực hiện phát hành cây dưới dạng tar-ball, v.v."

Tuy nhiên, việc kiểm tra nhật ký khá dễ dàng - nếu bạn đang theo dõi chi nhánh ổn định của foo.el, bạn có thể thấy những cam kết mới trong nhật ký của chi nhánh ổn định không có trong bản sao cục bộ của bạn. Nếu bạn muốn mô phỏng số phiên bản nội bộ của CVS, bạn có thể so sánh dấu thời gian của lần xác nhận cuối cùng.

Chỉnh sửa: bạn nên viết hoặc sử dụng tập lệnh của người khác cho việc này, tất nhiên, không làm điều này bằng tay.


26
Vâng, tôi đã đọc một phần của chuỗi email dài về việc mở rộng từ khóa. Thái độ của Linus gần như đủ để loại bỏ tôi hoàn toàn.
Joe Casadonte

15
Vâng, đôi khi anh ấy thiếu lịch sự nhưng anh ấy thường chính xác, và anh ấy chắc chắn là về chủ đề mở rộng từ khóa.
Bombe

Theo dõi phiên bản là cần thiết. git được sử dụng trong rất nhiều cơ sở hạ tầng khác bên cạnh sự phát triển thuần túy nơi người ta có thể đọc mã để xác định xem nó có hợp lý hay không. Nhưng khi một hệ thống kiểm soát sửa đổi được sử dụng để theo dõi các tệp có nội dung tùy ý thì bạn phải có một số phương tiện để biết bản phát hành chính thức. git, huống chi git log không có trên máy mà .ini, .conf, .html và các tệp khác đã được đẩy.
rjt

7
Linus chỉ nhận xét về một khía cạnh của việc mở rộng từ khóa - theo dõi phát hành. Nhưng đó không phải là mục đích duy nhất của nó. Câu nói đó thể hiện rõ thái độ của một người đàn ông, nhưng nói rằng không có gì hữu ích về chủ đề này. Một mánh khóe chính trị "nói rõ ràng theo cách xuất chúng", và đám đông là của bạn. Vấn đề là đám đông theo định nghĩa ngu ngốc, bởi vì nó chỉ có một bộ não trên tất cả. Mà giải thích tình hình với git và mở rộng từ khóa rõ ràng. Một thằng ngốc nói "không" và mọi người cổ vũ!
AnrDaemon

1
@AnrDaemon không chỉ vậy, git ngay từ khi thêm hỗ trợ $Id$thông qua identthuộc tính, như đã đề cập trong một câu trả lời khác ở đây, cho thấy ngay cả chính git cũng không phải là con tin theo ý kiến ​​của Linus.
orip

21

Như tôi đã viết trước đây :

Việc tự động tạo các thẻ Id hiển thị số phiên bản hợp lý là không thể thực hiện được với các công cụ DSCM như Bazaar vì dòng phát triển của mọi người có thể khác với tất cả các loại khác. Vì vậy, ai đó có thể tham khảo phiên bản Phiên bản 1.41 của một tập tin nhưng phiên bản của bạn, phiên bản 1.41, của tập tin đó thì khác.

Về cơ bản, $ Id $ không có ý nghĩa gì với Bazaar, Git và các công cụ quản lý mã nguồn phân tán khác.


6
Phải, tôi đã đọc nó trước khi đăng, và đó là lý do tại sao tôi yêu cầu một giải pháp tổng quát hơn cho vấn đề tiềm ẩn. Tôi nghĩ rằng mong muốn cho một tệp riêng lẻ có phiên bản # là hợp pháp, vì không có khả năng cung cấp giải pháp.
Joe Casadonte

Đó không phải là sự bất lực của Git, đó là sự bất lực của tất cả các SCM phân tán. Nếu bạn thực sự muốn số phiên bản có ý nghĩa, hãy sử dụng Subversion hoặc CVS ​​hoặc một số hệ thống tập trung khác.
Bombe

7
Có gì sai khi chỉ nhổ băm thay vì "số phiên bản"? Tôi muốn báo cáo nhật ký, gỡ lỗi trang web và tùy chọn "--version" trên các tập lệnh nội bộ sẽ dễ dàng cho tôi biết bản sửa đổi nào đang chạy ở đâu, vì vậy tôi có thể kiểm tra hàm băm cụ thể đó và xem tại sao nó hoạt động theo cách đó. Nó đơn giản hóa việc quản lý các ứng dụng đã triển khai .... và tôi không muốn một số hook hook coi mọi cam kết là một thay đổi đối với mọi tệp có thẻ $ Id $ trong đó.
nairbv

1
hàm băm của tệp bạn đang làm việc sẽ hoạt động giống như một "phiên bản", miễn là bạn có thể tra cứu nó trong git bởi id đó
Erik Aronesty

2
@Brian - theo chỉnh sửa của OP, người dùng cuối muốn biết số phiên bản nhưng không có quyền truy cập vào nhật ký git hoặc git. Trong trường hợp này, hàm băm là một số vô nghĩa, không phải là số phiên bản. Một DSCM không hỗ trợ trong việc giải quyết nhu cầu này.
Jesse Chisholm

10

Tôi đã từng gặp vấn đề tương tự. Tôi cần phải có một phiên bản đơn giản hơn chuỗi băm và có sẵn cho những người sử dụng công cụ mà không cần kết nối với kho lưu trữ.

Tôi đã làm điều đó với một hook pre-commit Git và thay đổi tập lệnh của tôi để có thể tự động cập nhật.

Tôi căn cứ phiên bản của số lượng cam kết thực hiện. Đây là một điều kiện cuộc đua nhẹ vì hai người có thể cam kết cùng một lúc và cả hai đều nghĩ rằng họ đang cam kết cùng một số phiên bản, nhưng chúng tôi không có nhiều nhà phát triển trong dự án này.

Ví dụ, tôi có một tập lệnh mà tôi đã đăng ký trong Ruby và tôi thêm mã này vào nó - đó là mã khá đơn giản để dễ dàng chuyển sang các ngôn ngữ khác nếu bạn đang kiểm tra một ngôn ngữ khác (mặc dù rõ ràng đây là sẽ không dễ dàng làm việc với các đăng ký không thể chạy được như tệp văn bản). Tôi đã thêm:

MYVERSION = '1.090'
## Call script to do updateVersion from .git/hooks/pre-commit
def updateVersion
  # We add 1 because the next commit is probably one more - though this is a race
  commits = %x[git log #{$0} | grep '^commit ' | wc -l].to_i + 1
  vers = "1.%0.3d" % commits

  t = File.read($0)
  t.gsub!(/^MYVERSION = '(.*)'$/, "MYVERSION = '#{vers}'")
  bak = $0+'.bak'
  File.open(bak,'w') { |f| f.puts t }
  perm = File.stat($0).mode & 0xfff
  File.rename(bak,$0)
  File.chmod(perm,$0)
  exit
end

Và sau đó tôi thêm một tùy chọn dòng lệnh (-updateVersion) vào tập lệnh để nếu tôi gọi nó là "tool -updateVersion" thì nó chỉ gọi updateVersion cho công cụ tự sửa đổi giá trị "MYVERSION" và sau đó thoát ra (bạn có thể có nó cũng cập nhật các tập tin khác nếu chúng cũng được mở nếu bạn muốn).

Sau khi thiết lập xong, tôi đi đến phần đầu Git và tạo một tập lệnh bash một dòng có thể thực thi được .git/hooks/pre-commit.

Kịch bản chỉ đơn giản là thay đổi thành phần đầu của thư mục Git và gọi tập lệnh của tôi với -updateVersion.

Mỗi lần tôi kiểm tra tập lệnh xác nhận trước được chạy sẽ chạy tập lệnh của tôi với -updateVersion và sau đó biến MYVERSION được cập nhật dựa trên số lần xác nhận. Ma thuật!


Vì vậy, tập lệnh Ruby của bạn phải được gọi là updateVersion để có git updateVersion? Vui lòng đặt một số mẫu về cách nó được gọi.
rjt

Tôi tạo một tùy chọn (-updateVersion) cho tập lệnh mà tôi đang kiểm tra để gọi hàm 'updateVersion' (trong trường hợp này tôi đang cố gắng thay đổi số phiên bản trong chính tập lệnh). Sau đó, tôi chỉ cần thực hiện một lệnh shell oneliner gọi tập lệnh của tôi bằng -updateVersion, và sau đó nó tự cập nhật trước mỗi lần đăng ký.
David Ljung Madison Stellar

8

Nếu có $ Keywords $ là điều cần thiết cho bạn, thì có lẽ bạn có thể thử xem Mercurial thay thế? Nó có một phần mở rộng hgkeyword thực hiện những gì bạn muốn. Dù sao thì Mercurial cũng thú vị như một DVCS.


8

Một cái gì đó được thực hiện với kho Git là sử dụng tagđối tượng. Điều này có thể được sử dụng để gắn thẻ một cam kết với bất kỳ loại chuỗi nào và có thể được sử dụng để đánh dấu các phiên bản. Bạn có thể thấy các thẻ đó trong một kho lưu trữ với git taglệnh, trả về tất cả các thẻ.

Thật dễ dàng để kiểm tra một thẻ. Ví dụ: nếu có thẻ v1.1bạn có thể kiểm tra thẻ đó ra một nhánh như thế này:

git checkout -b v1.1

Vì nó là một đối tượng cấp cao nhất, bạn sẽ thấy toàn bộ lịch sử cho cam kết đó, cũng như có thể chạy các khác biệt, thực hiện các thay đổi và hợp nhất.

Không chỉ vậy, nhưng một thẻ vẫn tồn tại, ngay cả khi nhánh mà nó được mở đã bị xóa mà không được sáp nhập trở lại vào dòng chính.


6
Vậy thì, có cách nào để thẻ này được tự động chèn vào tệp không? Cảm ơn!
Joe Casadonte

1
Nếu bạn có nghĩa là mở rộng từ khóa? Không xa như tôi biết. nếu bạn đang xây dựng sản phẩm, bạn có thể lấy thông tin như một phần của tập lệnh xây dựng của mình và chèn nó vào đâu đó vào sản phẩm được xây dựng của bạn. Hãy thử man git-description cung cấp thẻ mới nhất, số lần xác nhận kể từ thẻ này và hàm băm hiện tại.
Abizern

Có, thẻ và thông tin liên quan khác hiện có thể được chỉnh sửa thành các tệp tự động bằng git thông qua export-substtính năng của gitattributes(5). Tất nhiên, điều này đòi hỏi phải sử dụng git archiveđể tạo các bản phát hành và chỉ trong tệp tar kết quả mới có thể hiển thị các chỉnh sửa thay thế.
Greg A. Woods

4

Nếu tôi hiểu chính xác, về cơ bản, bạn muốn biết có bao nhiêu cam kết đã xảy ra trên một tệp nhất định kể từ khi bạn cập nhật lần cuối.

Trước tiên, hãy lấy các thay đổi trong nguồn gốc từ xa, nhưng đừng hợp nhất chúng vào masterchi nhánh của bạn :

% git fetch

Sau đó nhận nhật ký về những thay đổi đã xảy ra trên một tệp nhất định giữa masterchi nhánh của bạn và điều khiển từ xa origin/master.

% git log master..origin/master foo.el

Điều này cung cấp cho bạn các thông điệp tường trình của tất cả các cam kết đã xảy ra trong kho lưu trữ từ xa kể từ lần cuối bạn sáp nhập origin/mastervàomaster .

Nếu bạn chỉ muốn đếm số lượng thay đổi, hãy chuyển nó sang wc. Nói như thế này:

% git rev-list master..origin/master foo.el | wc -l

1
Vì vậy, đừng sử dụng log: git rev-list master..origin / master | wc -l
Dustin

4

Nếu bạn chỉ muốn mọi người có thể biết được họ đã lỗi thời đến mức nào, Git có thể thông báo cho họ về điều đó theo một số cách khá dễ dàng. Họ so sánh ngày của cam kết cuối cùng trên thân cây của họ và thân cây của bạn, ví dụ. Họ có thể sử dụnggit cherry để xem có bao nhiêu cam kết đã xảy ra trong thân cây của bạn không có trong họ.

Nếu đó là tất cả những gì bạn muốn, tôi sẽ tìm cách cung cấp nó mà không cần số phiên bản.

Ngoài ra, tôi sẽ không mở rộng phép lịch sự cho bất cứ ai trừ khi bạn chắc chắn họ muốn điều đó. :)


Nếu ngày tháng là OK để so sánh, hãy đặt DateTImeStamp trong tệp. git có rất nhiều trường hợp sử dụng khác ngoài chỉ các nhà phát triển. CNTT trong lĩnh vực này cần biết liệu tệp .INI hoặc .conf trên máy trạm hiện đang được khắc phục sự cố ở bất kỳ nơi nào gần với hiện tại.
rjt

Một dấu thời gian chỉ là đủ? Chi nhánh sai có thể có dấu thời gian hấp dẫn và vẫn ít chính xác hơn.
dùng2066657

4

Để áp dụng mở rộng cho tất cả các tệp trong tất cả các thư mục con trong kho lưu trữ, hãy thêm một .gitattributestệp vào thư mục cấp cao nhất trong kho lưu trữ (tức là nơi bạn thường đặt .gitignoretệp) có chứa:

* ident

Để thấy điều này có hiệu lực, trước tiên bạn cần thực hiện kiểm tra hiệu quả các (các) tệp, chẳng hạn như xóa hoặc chỉnh sửa chúng theo bất kỳ cách nào. Sau đó khôi phục chúng bằng:

git checkout .

Và bạn sẽ thấy $Id$ thay thế bằng một cái gì đó như:

$Id: ea701b0bb744c90c620f315e2438bc6b764cdb87 $

Từ man gitattributes :

xác định

Khi nhận dạng thuộc tính được đặt cho một đường dẫn, Git thay thế $ Id $ trong đối tượng blob bằng $ Id:, theo sau là tên đối tượng blob thập lục phân 40 ký tự, theo sau là ký hiệu đô la $ khi thanh toán. Bất kỳ chuỗi byte nào bắt đầu bằng $ Id: và kết thúc bằng $ trong tệp worktree được thay thế bằng $ Id $ khi đăng ký.

ID này sẽ thay đổi mỗi khi một phiên bản mới của tệp được cam kết.


3

ID RCS rất tốt cho các dự án một tệp, nhưng đối với bất kỳ ai khác, $ Id $ không nói gì về dự án (trừ khi bạn buộc phải đăng ký giả cho tệp phiên bản giả).

Vẫn có thể quan tâm làm thế nào để có được các số tương đương của $ Author $, $ Date $, $ Revision $, $ RCSfile $, v.v. trên mỗi cấp độ tệp hoặc ở cấp độ cam kết (cách đặt chúng ở nơi một số từ khóa là một từ khóa khác câu hỏi). Tôi không có câu trả lời về những điều này, nhưng hãy xem yêu cầu cập nhật chúng, đặc biệt là khi các tệp (hiện có trong Git) có nguồn gốc từ các hệ thống tương thích RCS (CVS).

Những từ khóa như vậy có thể thú vị nếu các nguồn được phân phối riêng biệt từ bất kỳ kho lưu trữ Git nào (đó là điều tôi cũng làm). Giải pháp của tôi là như thế này:

Mỗi dự án đều có một thư mục riêng và trong thư mục gốc tôi có một tệp văn bản có tên .version nội dung mô tả phiên bản hiện tại (tên sẽ được sử dụng khi xuất các nguồn).

Trong khi làm việc cho bản phát hành tiếp theo, tập lệnh trích xuất .versionsố đó , một số mô tả phiên bản Git (như git describe) và số bản dựng đơn điệu trong .build(cộng với máy chủ và ngày) vào tệp nguồn được tạo tự động được liên kết với chương trình cuối cùng, vì vậy bạn có thể tìm thấy ra từ nguồn nào và khi nào nó được xây dựng.

Tôi phát triển các tính năng mới trong các nhánh riêng biệt và điều đầu tiên tôi làm là thêm n(cho "tiếp theo") vào .versionchuỗi (nhiều nhánh có nguồn gốc từ cùng một gốc sẽ sử dụng cùng một .versionsố tạm thời ). Trước khi phát hành, tôi quyết định hợp nhất các chi nhánh (hy vọng tất cả đều giống nhau .version). Trước khi thực hiện hợp nhất, tôi cập nhật .versionlên số tiếp theo (cập nhật chính hoặc phụ, tùy thuộc vào các tính năng được hợp nhất).


3

Nếu bạn muốn thông tin cam kết git có thể truy cập vào mã của bạn, thì bạn phải thực hiện một bước xây dựng trước để có được nó ở đó. Trong bash cho C / C ++, nó có thể trông giống như thế này:

prebuild.sh

#!/bin/bash
commit=$(git rev-parse HEAD)
tag=$(git describe --tags --always ${commit})
cat <<EOF >version.c
#include "version.h"
const char* git_tag="${tag}";
const char* git_commit="${commit}";
EOF

với version.hvẻ như:

#pragma once
const char* git_tag;
const char* git_commit;

Sau đó, bất cứ nơi nào bạn cần nó trong mã #include "version.h"và tài liệu tham khảo của bạn git_taghoặc git_commitkhi cần thiết.

Và bạn Makefilecó thể có một cái gì đó như thế này:

all: package
version:
  ./prebuild.sh
package: version
  # the normal build stuff for your project

Điều này có lợi ích của:

  • nhận các giá trị hiện tại chính xác cho bản dựng này bất kể phân nhánh, hợp nhất hái anh đào và như vậy.

Việc thực hiện prepublish.shnày có những nhược điểm của:

  • buộc biên dịch lại ngay cả khi git_tag/ git_commitkhông thay đổi.
  • nó không tính đến các tệp sửa đổi cục bộ chưa được cam kết nhưng ảnh hưởng đến việc xây dựng.
    • sử dụng git describe --tags --always --dirtyđể bắt trường hợp sử dụng đó.
  • gây ô nhiễm không gian tên toàn cầu.

Một fancier prebuild.shcó thể tránh những vấn đề này được để lại như một bài tập cho người đọc.


1

Tôi đồng ý với những người nghĩ rằng việc thay thế mã thông báo thuộc về các công cụ xây dựng hơn là các công cụ kiểm soát phiên bản.

Bạn nên có một số công cụ phát hành tự động để đặt ID phiên bản trong nguồn của mình tại thời điểm phát hành đang được gắn thẻ.


2
.INI .conf và .txt thường không có công cụ xây dựng.
rjt

Nhưng bạn có thể hack cùng một tập lệnh phát hành lấy thẻ Git hiện tại và ghi nó vào một tập tin, hoặc một cái gì đó thuộc loại này.
Marnen Laibow-Koser

1

Tên thẻ và thông tin liên quan khác hiện có thể được Git chỉnh sửa trực tiếp thành các tệp thông qua export-substtính năng của gitattributes(5). Tất nhiên, điều này đòi hỏi phải sử dụng git archiveđể tạo các bản phát hành và chỉ trong tệp tar kết quả mới có thể hiển thị các chỉnh sửa thay thế.

Ví dụ trong .gitattributestệp đặt dòng sau:

* export-subst

Sau đó, trong các tệp nguồn, bạn có thể thêm một dòng như thế này:

#ident  "@(#)PROJECTNAME:FILENAME:$Format:%D:%ci:%cN:%h$"

Và nó sẽ mở rộng để trông như thế này trong một bản phát hành được tạo bởi, ví dụ git archive v1.2.0.90:

#ident  "@(#)PROJECTNAME:FILENAME:HEAD -> master, tag: v1.2.0.90:2020-04-03 18:40:44 -0700:Greg A. Woods:e48f949"

0

Vì bạn sử dụng Emacs, bạn có thể may mắn :)

Tôi đã tình cờ gặp câu hỏi này và cũng là sự trùng hợp ngẫu nhiên tôi đã đến Lively vài ngày trước, một gói Emacs cho phép có những mẩu Emacs Lisp sống động trong tài liệu của bạn. Tôi đã không cố gắng thành thật, nhưng nó xuất hiện trong đầu tôi khi đọc nó.


0

Tôi cũng đến từ SCCS, RCS và CVS ( %W% %G% %U%).

Tôi đã có một thử thách tương tự. Tôi muốn biết phiên bản nào của một đoạn mã trên bất kỳ hệ thống nào chạy nó. Hệ thống có thể hoặc không thể kết nối với bất kỳ mạng nào. Hệ thống có thể có hoặc không cài đặt Git. Hệ thống có thể có hoặc không có kho lưu trữ GitHub được cài đặt trên nó.

Tôi muốn cùng một giải pháp cho một số loại mã (.sh, .go, .yml, .xml, v.v.). Tôi muốn bất kỳ người nào không có kiến ​​thức về Git hoặc GitHub có thể trả lời câu hỏi "Bạn đang chạy phiên bản nào?"

Vì vậy, tôi đã viết những gì tôi gọi là một trình bao bọc xung quanh một vài lệnh Git. Tôi sử dụng nó để đánh dấu một tập tin với một số phiên bản và một số thông tin. Nó giải quyết thách thức của tôi. Nó có thể giúp bạn.

https://github.com/BradleyA/markit

git clone https://github.com/BradleyA/markit
cd markit

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.