Cách tốt để quản lý một thay đổi bằng cách sử dụng git?


214

Tôi đã sử dụng Git được một thời gian và gần đây tôi đã bắt đầu sử dụng nó để gắn thẻ các bản phát hành của mình để tôi có thể dễ dàng theo dõi các thay đổi hơn và có thể xem phiên bản nào mà mỗi khách hàng của chúng tôi đang chạy (không may là mã hiện đang bắt buộc rằng mỗi khách hàng có bản sao riêng của trang web PHP; tôi đang thay đổi trang này, nhưng nó sẽ chậm).

Trong mọi trường hợp, chúng tôi đang bắt đầu xây dựng một số động lực, tôi nghĩ rằng nó sẽ thực sự tốt để có thể cho mọi người thấy những gì đã thay đổi kể từ lần phát hành trước. Vấn đề là, tôi đã không duy trì một sự thay đổi bởi vì tôi không có ý tưởng hay về cách thực hiện nó. Trong thời gian đặc biệt này, tôi có thể chạy qua nhật ký và tự tạo một bản ghi, nhưng điều đó sẽ rất mệt mỏi.

Tôi đã thử googling "git changelog" và "git Manage changelog" nhưng tôi không tìm thấy bất cứ điều gì thực sự nói về quy trình thay đổi mã và làm thế nào trùng khớp với changelog. Chúng tôi hiện đang theo quy trình phát triển của Rein Henrichs và tôi sẽ thích thứ gì đó đi cùng với nó.

Có một cách tiếp cận tiêu chuẩn mà tôi đang thiếu, hay đây là một lĩnh vực mà mọi người đều làm việc của riêng mình?

Cảm ơn rất nhiều cho ý kiến ​​/ câu trả lời của bạn!

Câu trả lời:


181

Điều này là khoảng 3-4 năm trước, nhưng vì lợi ích của những người tìm kiếm trong tương lai, giờ đây có thể tạo ra các bản ghi tuyệt đẹp với:

git log --oneline --decorate

Hoặc, nếu bạn muốn nó thậm chí đẹp hơn (có màu cho thiết bị đầu cuối):

git log --oneline --decorate --color

Đường ống đầu ra đó đến ChangeLog là những gì tôi hiện đang sử dụng trong tất cả các dự án của mình, điều đó thật tuyệt vời.


4
Một thẻ hữu ích khác là --graph, hiển thị trực quan cho bạn các nhánh mà các cam kết được bật.
Bỏ trốn

44
Tôi đặc biệt khuyên bạn không nên sử dụng nhật ký quà tặng khác với tư cách là THAY ĐỔI
Olivier Lacan

4
sao chép git logđầu ra để thay đổi không có ý nghĩa. Bạn cần thực hiện công việc lọc và chỉnh sửa để có một thay đổi có thể đọc được, nếu không, tại sao bạn thậm chí cần một thay đổi? Tôi nghĩ bạn có thể tự động hóa việc tạo ra một thay đổi nhưng xin đừng sao chép thô git log!
vaab 11/03/2015

19
Vấn đề với điều này là, ngay cả khi giả sử rằng mọi người đóng góp cho dự án của bạn đều viết các thông điệp cam kết rõ ràng và dễ đọc, bạn vẫn sẽ tạo ra một "thay đổi" có chứa TẤN tiếng ồn. Thay đổi nên được viết với mục tiêu giải thích cho người dùng dự án của bạn về những thay đổi đáng chú ý liên quan đến chúng xảy ra giữa các bản phát hành, trong khi thông điệp cam kết nên tập trung vào giải thích cho nhà phát triển những cải tiến mà cam kết của bạn tạo ra cho mã . Đôi khi có sự chồng chéo ở đó, nhưng không phải lúc nào cũng vậy.
Ajedi32

7
Hoặc, để làm cho cụ thể hơn một chút, phương pháp này sẽ tạo ra một "nhật ký thay đổi" chứa nhiều mục như "Đã sửa lỗi chính tả của fooMethod trong ZModule" và "Refactor XModule để sử dụng phiên bản XYLibarary mới". Người dùng của bạn không quan tâm đến điều đó. Họ muốn biết những thay đổi đã được thực hiện từ quan điểm của họ với tư cách là người dùng, chứ không phải quan điểm của bạn với tư cách là nhà phát triển. Và thậm chí còn bỏ qua những thứ như "Hợp nhất PR # 123 từ xdev / foo" và "Opps, đã sửa lỗi NewFeature để nó thực sự hoạt động" loại những thứ có khả năng tồn tại trong bất kỳ repo nào trong thế giới thực.
Ajedi32

60

Bạn có thể sử dụng một số hương vị của nhật ký git để giúp bạn:

git log --pretty=%s                 # only print the subject

Nếu bạn đặt tên cho các nhánh của mình một cách độc đáo, để hợp nhất thành chủ hiển thị dưới dạng một cái gì đó như "Hợp nhất nhánh tính năng-foobar", bạn có thể rút ngắn mọi thứ bằng cách chỉ hiển thị thông báo đó, và không phải tất cả các cam kết nhỏ mà bạn đã hợp nhất, cùng nhau tạo thành đặc tính:

git log --pretty=%s --first-parent  # only follow first parent of merges

Bạn có thể có thể tăng cường điều này bằng một tập lệnh của riêng bạn, có thể thực hiện những việc như loại bỏ các bit "Chi nhánh hợp nhất", bình thường hóa định dạng, v.v ... Tại một số điểm, dĩ nhiên bạn phải tự viết nó.

Sau đó, bạn có thể tạo một phần mới cho thay đổi một lần cho mỗi phiên bản:

git log [opts] vX.X.X..vX.X.Y | helper-script > changelogs/X.X.Y

và cam kết rằng trong phiên bản phát hành của bạn cam kết.

Nếu vấn đề của bạn là những đối tượng cam kết đó không giống với những gì bạn muốn đưa vào thay đổi, thì bạn có khá nhiều lựa chọn: tiếp tục làm mọi thứ thủ công (và cố gắng theo kịp nó thường xuyên hơn thay vì chơi đuổi bắt- tại thời điểm phát hành) hoặc sửa chữa kiểu tin nhắn cam kết của bạn. Một tùy chọn, nếu các đối tượng sẽ không làm điều đó cho bạn, sẽ đặt các dòng như "thay đổi: thêm tính năng foobar" trong phần thân của các thông điệp cam kết của bạn, để sau này bạn có thể làm gì đó git log --pretty=%B | grep ^change:để chỉ lấy những siêu phẩm đó bit quan trọng của các tin nhắn.

Tôi không hoàn toàn chắc chắn bao nhiêu hơn git đó thực sự có thể giúp bạn tạo ra các thay đổi của bạn. Có lẽ tôi đã hiểu sai ý của bạn khi nói "quản lý"?


2
Đó chắc chắn là một khởi đầu tuyệt vời và tôi đã không nghĩ đến việc thêm một công cụ sửa đổi vào cơ thể để tôi có thể grep nó sau này. Đó có thể là những gì tôi kết thúc làm. Cảm ơn vì bạn đã phản hồi! Nếu không có thêm câu trả lời nào trong ngày hôm sau hoặc lâu hơn, tôi sẽ đánh dấu câu trả lời của bạn là câu trả lời :-)
Topher Fangio

60

TUYÊN BỐ TỪ CHỐI: Tôi là tác giả của gitchangelog mà tôi sẽ nói sau đây.

TL; DR: Bạn có thể muốn kiểm tra thay đổi riêng của gitchangelog hoặc đầu ra ascii đã tạo trước đó.

Nếu bạn muốn tạo một thay đổi từ lịch sử git của mình, có lẽ bạn sẽ phải xem xét:

  • các định dạng đầu ra . (ASCII tùy chỉnh thuần túy, loại thay đổi Debian, Markdow, ReST ...)
  • một số bộ lọc cam kết (có thể bạn không muốn thấy tất cả các thay đổi của typo hoặc mỹ phẩm nhận được trong thay đổi của bạn)
  • một số cam kết văn bản lộn xộn trước khi được đưa vào thay đổi. (Đảm bảo bình thường hóa các tin nhắn có chữ hoa đầu tiên hoặc dấu chấm cuối cùng, nhưng nó cũng có thể xóa một số đánh dấu đặc biệt trong bản tóm tắt)
  • lịch sử git của bạn có tương thích không? Việc hợp nhất, gắn thẻ, không phải lúc nào cũng dễ dàng được hỗ trợ bởi hầu hết các công cụ. Nó phụ thuộc vào cách bạn quản lý lịch sử của bạn.

Tùy chọn bạn có thể muốn một số phân loại (những điều mới, thay đổi, sửa lỗi) ...

Với tất cả những điều này, tôi đã tạo và sử dụng gitchangelog . Nó có nghĩa là tận dụng một quy ước thông điệp cam kết git để đạt được tất cả các mục tiêu trước đó.

Có một quy ước thông điệp cam kết là bắt buộc để tạo ra một thay đổi tốt đẹp (có hoặc không sử dụng gitchangelog).

cam kết thông điệp

Sau đây là những gợi ý về những gì có thể hữu ích để suy nghĩ về việc thêm vào các thông điệp cam kết của bạn.

Bạn có thể muốn tách khoảng cam kết của mình thành các phần lớn:

  • theo ý định (ví dụ: mới, sửa chữa, thay đổi ...)
  • theo đối tượng (ví dụ: doc, bao bì, mã ...)
  • theo đối tượng (ví dụ: dev, người kiểm tra, người dùng ...)

Ngoài ra, bạn có thể muốn gắn thẻ một số cam kết:

  • như "cam kết" nhỏ không nên xuất ra thay đổi của bạn (thay đổi mỹ phẩm, lỗi đánh máy nhỏ trong nhận xét ...)
  • là "tái cấu trúc" nếu bạn không thực sự có bất kỳ thay đổi tính năng quan trọng nào. Do đó, đây cũng không phải là một phần của thay đổi được hiển thị cho người dùng cuối cùng, nhưng có thể được quan tâm nếu bạn có một thay đổi nhà phát triển.
  • bạn cũng có thể gắn thẻ bằng "api" để đánh dấu các thay đổi API hoặc công cụ API mới ...
  • ...Vân vân...

Cố gắng viết thông điệp cam kết của bạn bằng cách nhắm mục tiêu người dùng (chức năng) thường xuyên nhất có thể.

thí dụ

Đây là tiêu chuẩn git log --onelineđể cho thấy những thông tin này có thể được lưu trữ như thế nào ::

* 5a39f73 fix: encoding issues with non-ascii chars.
* a60d77a new: pkg: added ``.travis.yml`` for automated tests. 
* 57129ba new: much greater performance on big repository by issuing only one shell command for all the commits. (fixes #7)
* 6b4b267 chg: dev: refactored out the formatting characters from GIT.
* 197b069 new: dev: reverse ``natural`` order to get reverse chronological order by default. !refactor 
* 6b891bc new: add utf-8 encoding declaration !minor 

Vì vậy, nếu bạn nhận thấy, định dạng tôi chọn là:

{new|chg|fix}: [{dev|pkg}:] COMMIT_MESSAGE [!{minor|refactor} ... ]

Để xem kết quả đầu ra thực tế, bạn có thể nhìn vào phần cuối của trang PyPI của gitchangelog

Để xem tài liệu đầy đủ về quy ước thông điệp cam kết của tôi, bạn có thể xem tệp tham chiếu gitchangelog.rc.reference

Làm thế nào để tạo ra thay đổi tinh tế từ đây

Sau đó, thật dễ dàng để thực hiện một thay đổi hoàn toàn. Bạn có thể tạo tập lệnh của riêng mình khá nhanh hoặc sử dụng gitchangelog.

gitchangelogsẽ tạo ra một thay đổi đầy đủ (có hỗ trợ phân đoạn như New, Fix...) và có thể cấu hình hợp lý theo các quy ước cam kết của riêng bạn. Nó hỗ trợ bất kỳ loại đầu ra nhờ templating qua Mustache, Mako templatingvà có một động cơ di sản mặc định viết bằng python liệu; tất cả 3 công cụ hiện tại đều có ví dụ về cách sử dụng chúng và có thể xuất ra các thay đổi như một công cụ được hiển thị trên trang PyPI của gitchangelog.

Tôi chắc chắn rằng bạn biết rằng có rất nhiều khác git logđể changelogcông cụ hiện có cũng có.


1
Điều này thật tuyệt vời, chính xác là những gì tôi đang tìm kiếm. Tôi sẽ thử nó, cảm ơn bạn rất nhiều!
Jeff Kiiza

26

Thêm một điểm đến THAY ĐỔI. Hãy cho tôi biết nếu bạn mọi người thích nó.

git log --since=1/11/2011 --until=28/11/2011 --no-merges --format=%B

Kiểu này thực hiện điều đó: Tôi sẽ thêm các tham số khác vào --format, như được giải thích trong git-scm.com/docs/git-log#_pretty_formats
bluesmonk

23

Các gitlog-to-changelogkịch bản có ích để tạo ra một GNU kiểu ChangeLog.

Như được hiển thị bởi gitlog-to-changelog --help, bạn có thể chọn các cam kết được sử dụng để tạo ChangeLogtệp bằng tùy chọn --since:

gitlog-to-changelog --since=2008-01-01 > ChangeLog

hoặc bằng cách chuyển các đối số bổ sung sau --, sẽ được chuyển đến git-log(được gọi bên trong bởi gitlog-to-changelog):

gitlog-to-changelog -- -n 5 foo > last-5-commits-to-branch-foo

Chẳng hạn, tôi đang sử dụng quy tắc sau ở cấp cao nhất Makefile.amcủa một trong các dự án của mình:

.PHONY: update-ChangeLog
update-ChangeLog:
    if test -d $(srcdir)/.git; then                         \
       $(srcdir)/build-aux/gitlog-to-changelog              \
          --format='%s%n%n%b%n' --no-cluster                \
          --strip-tab --strip-cherry-pick                   \
          -- $$(cat $(srcdir)/.last-cl-gen)..               \
        >ChangeLog.tmp                                      \
      && git rev-list -n 1 HEAD >.last-cl-gen.tmp           \
      && (echo; cat $(srcdir)/ChangeLog) >>ChangeLog.tmp    \
      && mv -f ChangeLog.tmp $(srcdir)/ChangeLog            \
      && mv -f .last-cl-gen.tmp $(srcdir)/.last-cl-gen      \
      && rm -f ChangeLog.tmp;                               \
    fi

EXTRA_DIST += .last-cl-gen

Quy tắc này được sử dụng tại thời điểm phát hành để cập nhật ChangeLogcác thông báo cam kết chưa được ghi lại mới nhất. Tệp .last-cl-genchứa định danh SHA1 của cam kết mới nhất được ghi lại ChangeLogvà được lưu trữ trong kho Git. ChangeLogcũng được ghi lại trong kho lưu trữ, để nó có thể được chỉnh sửa (ví dụ để sửa lỗi chính tả) mà không thay đổi các thông điệp cam kết.


Kịch bản mklog GCC cũng có thể thú vị: stackoverflow.com/a/31606865/895245
Ciro Santilli 郝海东 冠状 病

Đây sẽ là dự án chiến thắng! Tại sao bạn không có nó trên github?
Omer Dagan

20

Vì việc tạo thẻ cho mỗi phiên bản là cách tốt nhất, bạn có thể muốn phân vùng thay đổi cho mỗi phiên bản. Trong trường hợp đó, lệnh này có thể giúp bạn:

git log YOUR_LAST_VERSION_TAG..HEAD --no-merges --format=%B

15

Đối với các dự án GitHub, nó có thể hữu ích: github-changelog-Generator

Nó tạo ra các thay đổi từ các vấn đề đã đóng của thẻ và các yêu cầu kéo được hợp nhất.

Đây CHANGELOG.md được tạo ra bởi kịch bản này.

Thí dụ:

Thay đổi

1.2.5 (2015-01-15)

Thay đổi đầy đủ

Cải tiến thực hiện:

  • Sử dụng cột mốc để chỉ định lỗi phiên bản nào đã được sửa # 22

Đã sửa lỗi:

  • Lỗi khi cố gắng tạo nhật ký cho repo mà không có thẻ # 32

Yêu cầu kéo hợp nhất:

  • Lớp PrettyPrint được bao gồm sử dụng chữ thường 'pp' # 43 ( schwing )

  • hỗ trợ github doanh nghiệp thông qua tùy chọn dòng lệnh # 42 ( glenlovett )


Những dự án như vậy là tốt nhất :) Động lực của bạn để làm điều đó là gì? Cũng nhờ vào cảm hứng của bạn, tôi đã tạo ra một công cụ tương tự, hoạt động mà không có nhãn, chia thành Đã thêm / Thay đổi / Đã sửa / Đã xóa và bằng PHP (ngôn ngữ "bản địa" của tôi): github.com/Symplify/CheachogLinker Bạn có viết bài về Changlogs không ? Tôi muốn đọc chúng
Tomáš Votruba

1
@ TomášVotruba cảm ơn vì những lời ấm áp. Đó chỉ là sở thích của tôi. Tôi đã không đăng rất nhiều. Nhưng tôi nghĩ nó đáng giá. Lời chúc tốt nhất!
skywinder

10

Tôi cũng đã làm một thư viện cho việc này. Nó có thể cấu hình đầy đủ với một mẫu Mustache. Điều đó có thể:

  • Được lưu trữ vào tập tin, như CHANGELOG.md .
  • Được đăng lên MediaWiki
  • Hoặc chỉ được in ra STDOUT

Tôi cũng đã thực hiện:

Thêm chi tiết về Github: https://github.com/tomasbjerre/git-changelog-lib

Từ dòng lệnh:

npx git-changelog-command-line -std -tec "
# Changelog

Changelog for {{ownerName}} {{repoName}}.

{{#tags}}
## {{name}}
 {{#issues}}
  {{#hasIssue}}
   {{#hasLink}}
### {{name}} [{{issue}}]({{link}}) {{title}} {{#hasIssueType}} *{{issueType}}* {{/hasIssueType}} {{#hasLabels}} {{#labels}} *{{.}}* {{/labels}} {{/hasLabels}}
   {{/hasLink}}
   {{^hasLink}}
### {{name}} {{issue}} {{title}} {{#hasIssueType}} *{{issueType}}* {{/hasIssueType}} {{#hasLabels}} {{#labels}} *{{.}}* {{/labels}} {{/hasLabels}}
   {{/hasLink}}
  {{/hasIssue}}
  {{^hasIssue}}
### {{name}}
  {{/hasIssue}}

  {{#commits}}
**{{{messageTitle}}}**

{{#messageBodyItems}}
 * {{.}} 
{{/messageBodyItems}}

[{{hash}}](https://github.com/{{ownerName}}/{{repoName}}/commit/{{hash}}) {{authorName}} *{{commitTime}}*

  {{/commits}}

 {{/issues}}
{{/tags}}
"

Hoặc trong Jenkins:

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


3
git log --oneline --no-merges `git describe --abbrev=0 --tags`..HEAD | cut -c 9- | sort

Là những gì tôi thích sử dụng. Nó nhận được tất cả các cam kết kể từ thẻ cuối cùng. cutthoát khỏi hàm băm cam kết. Nếu bạn sử dụng số vé ở đầu tin nhắn cam kết của mình, chúng sẽ được nhóm với sort. Phân loại cũng giúp nếu bạn có tiền tố cam kết chắc chắn với fix, typovv


3

Tôi để máy chủ CI chuyển các phần sau vào một tệp có tên CHANGELOGcho mỗi bản phát hành mới với ngày được đặt trong tên tệp phát hành:

>git log --graph --all --date=relative --pretty=format:"%x09 %ad %d %s (%aN)"

2

Đối với thay đổi kiểu GNU , tôi đã nấu hàm

gnuc() {
  {
    printf "$(date "+%Y-%m-%d")  John Doe  <john.doe@gmail.com>\n\n"
    git diff-tree --no-commit-id --name-only -r HEAD | sed 's/^/\t* /'
  } | tee /dev/tty | xsel -b
}

Với cái này:

  • Tôi cam kết các thay đổi của mình định kỳ để sao lưu và khởi động lại chúng trước khi thực hiện chỉnh sửa cuối cùng cho ChangeLog
  • sau đó chạy: gnuc

và bây giờ clipboard của tôi chứa một cái gì đó như:

2015-07-24  John Doe  <john.doe@gmail.com>

        * gdb/python/py-linetable.c (): .
        * gdb/python/py-symtab.c (): .

Sau đó, tôi sử dụng bảng tạm làm điểm bắt đầu để cập nhật ChangeLog.

Nó không hoàn hảo (ví dụ: các tệp phải liên quan đến đường dẫn ChangeLog của chúng, vì vậy python/py-symtab.cmà không cần gdb/tôi sẽ chỉnh sửa gdb/ChangeLog), nhưng là một điểm khởi đầu tốt.

Kịch bản nâng cao hơn:

Tôi phải đồng ý với Tromey: sao chép dữ liệu cam kết git trong ChangeLog là vô ích.

Nếu bạn định tạo một thay đổi, hãy làm cho nó một bản tóm tắt tốt về những gì đang diễn ra, có thể như được chỉ định tại http://keepachangelog.com/


2

Dựa trên bithavoc , nó liệt kê last tagcho đến khi HEAD. Nhưng tôi hy vọng sẽ liệt kê các bản ghi giữa 2 thẻ.

// 2 or 3 dots between `YOUR_LAST_VERSION_TAG` and `HEAD`
git log YOUR_LAST_VERSION_TAG..HEAD --no-merges --format=%B

Liệt kê nhật ký giữa 2 thẻ.

// 2 or 3 dots between 2 tags
git log FROM_TAG...TO_TAG

Ví dụ, nó sẽ liệt kê các bản ghi từ v1.0.0đến v1.0.1.

git log v1.0.0...v1.0.1 --oneline --decorate

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.