3 điểm bởi GN⁺ 2024-02-02 | 1 bình luận | Chia sẻ qua WhatsApp
  • Commit “Convert template to US-ASCII to fix error” của Dan Carley, xuất hiện khi làm việc trên GOV.UK, cho thấy ngay cả một thay đổi mã nhỏ cũng có thể trở thành tài liệu dài hạn cho codebase nhờ thông điệp commit chi tiết
  • Một thông điệp tốt không chỉ ghi lại đã thay đổi gì mà còn để lại lý do tại sao thay đổi; trường hợp này ghi chép cụ thể lỗi invalid byte sequence in US-ASCII xảy ra khi chạy bundle exec rake và điều kiện để tái hiện
  • Vì chuỗi lỗi và quá trình điều tra được lưu lại cùng nhau, người gặp lại cùng vấn đề sau này có thể dùng git log --grep hoặc tìm kiếm commit trên GitHub để tìm hồ sơ giải quyết trước đó
  • Thông điệp còn bao gồm quá trình dùng các công cụ Unix như find -exec, file --mime, iconv, giúp reviewer và người đọc về sau có thể lần theo luồng xử lý sự cố
  • Không phải mọi commit đều cần dài đến mức này, nhưng những thông điệp giữ lại bối cảnh, quá trình điều tra và cả cảm xúc sẽ giúp xây dựng sự thấu hiểu chung về codebase và niềm tin trong nhóm

Một commit biến thay đổi nhỏ thành tài liệu dài hạn

  • Nếu được viết tốt, thông điệp commit Git có thể trở thành một công cụ tài liệu hóa mạnh mẽ tồn tại suốt vòng đời của codebase
  • Commit được nêu làm ví dụ là một thay đổi từ thời làm việc trên GOV.UK tại Government Digital Service
  • Tác giả là Dan Carley, và tiêu đề là “Convert template to US-ASCII to fix error”
  • Nhờ cách phát triển công khai của GDS, những trường hợp nội bộ của tổ chức như thế này cũng có thể được chia sẻ ra bên ngoài

Bối cảnh quan trọng hơn độ dài

  • So với lượng mã thay đổi, thông điệp của commit này khá dài, nhưng giá trị cốt lõi không nằm ở độ dài mà ở bối cảnh hữu ích
  • Cùng một thay đổi đó ở nơi khác có thể đã bị ghi ngắn gọn kiểu change whitespace, fix bug
  • Dan để lại bản ghi chi tiết để đồng nghiệp xung quanh và độc giả về sau có thể hiểu nguyên nhân vấn đề và quá trình xử lý

Không chỉ là thay đổi gì mà là vì sao thay đổi

  • Một thông điệp commit tốt không chỉ giải thích nội dung thay đổi mà còn cả lý do của thay đổi
  • Commit này ghi lại rằng sau khi thêm một bài kiểm thử để khớp với nội dung /etc/nginx/router_routes.conf trong feature branch, kết quả lại khác nhau tùy cách chạy
    • Chạy bằng bundle exec rake spec hoặc bundle exec rspec modules/router/spec thì hoạt động bình thường
    • Chạy bằng bundle exec rake thì từng khối should đều thất bại
    • Lỗi là ArgumentError: invalid byte sequence in US-ASCII
  • Nếu không có phần giải thích này, rất có thể người ta sẽ phải đoán xem công cụ nào đã gặp lỗi parse gì
  • Bối cảnh công việc ban đầu rất dễ biến mất khi con người quên đi, chuyển nhóm hoặc rời tổ chức

Hồ sơ lỗi có thể tìm kiếm được

  • Phần đầu thông điệp commit chứa nguyên văn thông báo lỗi đã dẫn tới thay đổi
  • Người gặp lại cùng lỗi có thể tìm lịch sử trước đó trong codebase theo các cách sau
  • Theo kết quả tìm kiếm, đã có nhiều người tìm lỗi này, và cũng có thể xác nhận ai là người gặp nó trước và đã thực hiện biện pháp gì

Ghi lại quá trình giải quyết vấn đề như một câu chuyện

  • Thông điệp được cấu trúc để người đọc có thể lần theo vấn đề xuất hiện ra sao, đã điều tra theo thứ tự nào và cuối cùng được sửa thế nào
  • Ví dụ, nó bao gồm việc lỗi biến mất khi bỏ matcher .with_content(//), file spec không có ký tự lạ, và việc có thể tái hiện khi require Puppet trong cùng một interpreter
  • Vì thông điệp commit ghi lại chính thay đổi chứ không phải chỉ một file, hàm hay một dòng mã cụ thể, đây là vị trí phù hợp để lưu lại hành trình mà codebase đã trải qua

Tác dụng phụ là mở rộng tri thức của cả nhóm

  • Dan đã ghi lại các lệnh được chạy ở từng bước điều tra, và đây có thể là cách lan truyền kiến thức nhẹ nhàng trong nhóm
  • Chỉ từ thông điệp commit, người đọc cũng có thể học cách dùng công cụ Unix
    • Có thể truyền đối số -exec cho find để chạy lệnh trên từng file được tìm thấy
    • Thêm \\+ ở cuối lệnh sẽ truyền nhiều tên file vào một lệnh file thay vì chạy một lần cho từng file
    • file --mime cho biết kiểu MIME của file
    • Có tồn tại một công cụ tên là iconv
  • Không chỉ người review thay đổi, mà cả người tìm lại commit này sau đó cũng nhận được cùng lượng thông tin
  • Khi có đủ thời gian và đủ commit tích lũy, những thông điệp như vậy có thể trở thành thiết bị khuếch đại tri thức của cả nhóm

Ghi chép tạo sự đồng cảm và niềm tin

  • Ở cuối commit có câu: “Now the tests work! One hour of my life I won't get back..”
  • Câu này truyền tải sự bực bội của một lập trình viên đã dành một giờ lần theo một bug khó chịu, cùng cảm giác thỏa mãn khi xử lý xong
  • Kể cả khi các đoạn hack ngắn hạn hay mã prototype đã đi vào production và bén rễ ở đó, những thông điệp như vậy vẫn nhắc ta rằng đằng sau mọi thay đổi đều từng có một con người đã đưa ra quyết định tốt nhất có thể với thông tin họ có lúc bấy giờ

Không phải mọi commit đều phải dài

  • Đây là một ví dụ khá cực đoan, và đặc biệt không cần kỳ vọng mọi commit có quy mô như thế đều phải chi tiết ở cùng mức độ
  • Dù vậy, đây vẫn là một ví dụ tốt về việc giải thích bối cảnh phía sau thay đổi, giúp người khác học hỏi, và đóng góp vào mô hình tinh thần chung về codebase của cả nhóm
  • Nếu bạn quan tâm đến thông điệp commit tốt và các công cụ để cấu trúc thay đổi, có thể xem các tài liệu sau

1 bình luận

 
GN⁺ 2024-02-02
Ý kiến trên Hacker News
  • Dù tốt hay xấu, từ góc nhìn của một đồng sáng lập GitHub và là người viết sách về Git như Pro Git, thông điệp commit Git là một con đường độc đáo để tài liệu hóa mã nguồn, nhưng lại rất kém hiệu quả.
    Vấn đề cốt lõi là hầu hết công cụ như Git, GitHub thường chỉ hiển thị dòng đầu tiên. Commit ví dụ cũng chỉ hiện một dòng chung chung như “US-ASCII error”, còn phần nội dung còn lại được bài viết khen ngợi thì trong các công cụ hiện đại gần như chẳng ai thấy.
    Git được thiết kế để thông điệp commit là phần thân email mà mọi người trong dự án đều đọc, nhưng ngày nay nhìn chung nó không còn đóng vai trò đó. Trừ khi thay đổi được thảo luận dưới dạng chuỗi patch trên mailing list, gần như không ai đọc gì ngoài 50 ký tự đầu của tiêu đề.
    Trong git blame, dù có tìm xem nên dùng -w -C -C -C hay hai -C để lần theo thông điệp liên quan, bạn vẫn chỉ thấy dòng đầu tiên; cuối cùng phải tìm SHA rồi chạy git show mới xem được thông điệp dài. Ngay cả khi viết tốt, việc tìm lại thông tin quá khó là một trong những phàn nàn lớn nhất của tôi về Git.
    Nhìn vào lịch sử dự án Git, thông điệp commit hầu như lần nào cũng xuất sắc, nhưng chỉ chạy blame trên một file cũng rất khó để lần theo bối cảnh của phần triển khai một hàm. Tài liệu hóa mà Jeff King để lại trong 10 năm qua đạt mức thiên tài, nhưng thật tệ là gần như không ai thưởng thức được.
    Tôi không biết giải pháp chính xác là gì, nhưng trong phần lớn cộng đồng, việc viết tài liệu xuất sắc bằng thông điệp commit đáng buồn là gần như lãng phí thời gian. Vì quá khó tìm.

    • Với tư cách là người đã đóng góp cho Git từ trước khi có GitHub và từng bảo trì mã legacy, tôi hoàn toàn không đồng ý. Tôi luôn dùng git blame, git log, git show trong terminal; việc lần theo lịch sử file rất dễ, và dùng git log -G để tìm thời điểm thêm/xóa chỉ mất vài giây.
      Điều khó chịu là khi đã tìm được commit mà thông điệp chỉ là “bleh” hoặc “add a thing”. Giá mà lập trình viên dành 60 giây để ghi lý do vì sao họ làm vậy.
      Ngược lại, khi tìm thấy một thông điệp commit giải thích chi tiết vì sao một thay đổi được thực hiện, tôi thật sự rất vui. Một thông điệp commit tốt có thể tiết kiệm hàng giờ, thậm chí hàng ngày làm việc.
      GitHub cũng góp phần vào vấn đề thông điệp commit tệ. Nếu may mắn thì mô tả PR có chi tiết, nhưng nó không nằm ngay cạnh commit log; thường thì PR dẫn tới link Jira, Jira dẫn tới link cuộc trò chuyện Slack, rồi Slack dẫn tới link tài liệu Google.
      Ngành này thật sự rất kém trong việc tài liệu hóa, nhưng những người như Jeff King đang chiến đấu đúng cách. Cuối cùng tôi nghĩ đây không phải vấn đề kỹ thuật mà là vấn đề con người. Viết tài liệu không có phần thưởng tức thì nên có cảm giác như việc làm thêm, còn lợi ích chỉ xuất hiện sau vài ngày, vài tuần hoặc vài tháng.
      Xin hãy viết thông điệp commit tốt. Chỉ cần dành 1 phút ghi lý do vì sao đã làm, không phải commit nào cũng trở thành một bài giải cho cái hàng rào chết tiệt của Chesterton. Hãy đặt nó vào thông điệp commit dễ tìm, bản thân bạn trong tương lai và tôi sẽ biết ơn.
      Nói thêm, tôi cũng không đồng ý với lập luận rằng thông điệp commit khó tìm. Tôi gần như không gặp khó khăn khi lần theo lịch sử của một dòng mã, một hàm hay một file; và ngay cả khi thông điệp commit không được đọc lại, nó vẫn có giá trị tại thời điểm viết. Viết thông điệp tốt khiến tôi kiểm tra xem mình có thật sự viết đúng đoạn mã như dự định không, và cũng có giá trị với người review code.
    • Tôi thấy khó tin câu “Git được thiết kế để thông điệp commit là phần thân email mà mọi người trong dự án đều đọc”. Thực tế thì gần với việc những người quan tâm đến chủ đề commit hoặc các file thay đổi đọc phần thân hơn; tôi không hiểu vì sao người khác lại phải đọc một tài liệu lịch sử bất biến.
      Nói rằng khó tìm tùy chọn git blame cũng nghe như đùa. Một IDE tốt sẽ gắn thông tin blame vào từng dòng, cho xem diff bằng một nút bấm, và từ diff đó phải có thể blame đệ quy các dòng ngữ cảnh hoặc các dòng đã bị xóa. Những công cụ như Tig làm đúng việc đó.
      Tôi thừa nhận GitHub khiến việc xem thông điệp commit trở nên khó khăn.
      Tài liệu gắn vào commit không phải được viết cho vui. Nó là cơ chế giảm rủi ro khi nhận patch từ một người có thể sau này không còn ở đó, đồng thời bộc lộ các suy nghĩ liên quan để người khác có thể làm tiếp trên nền đó. Nếu giấu suy nghĩ, quyền sở hữu độc quyền đối với mã sẽ tích tụ, và thường đó không phải điều tốt. Thông điệp commit cũng đóng vai trò bằng chứng công việc, và có thể trở nên quan trọng khi có quá nhiều patch. Trong các dự án thương mại, một phần tầm quan trọng này có thể thấp hơn.
    • Tôi không giỏi Git trên terminal, nhưng nếu dùng IntelliJ hoặc Magit của Emacs thì có thể dễ dàng tìm mọi commit đã thay đổi một file và duyệt toàn bộ thông điệp commit rất thuận tiện. Nếu dùng công cụ phù hợp thì không khó, và tôi nghĩ gần như ai cũng có công cụ tương tự. Thật sự cứ bám vào Git CLI và cố nhớ hàng trăm lệnh với flag để làm gì, tôi không hiểu.
    • Đây là thất bại của GitHub và các hệ thống tương tự. GitHub dường như cho rằng người dùng không thể suy luận từ lịch sử commit nên cố đơn giản hóa, và đây là một trong các hệ quả. Đặc biệt, sự hỗn loạn trong các repository GitHub riêng tư đôi khi khó tin đến mức không tưởng.
      Thật ra không có chỗ nào khác để đặt loại tài liệu này. Nó không phù hợp với comment trong mã. Nhưng giờ đã có một thế hệ lập trình viên nghĩ rằng Git chính là GitHub, và mục đích duy nhất của Git là đẩy thay đổi lên GitHub.
      Git không tuyệt, nhưng vẫn đỡ tệ hơn rất nhiều so với các thứ khác. Cần quay lại nền tảng và hiểu mục đích thực sự của quản lý phiên bản.
    • Dù vậy, nó vẫn rất tuyệt cho nghiên cứu lịch sử. Đây là một trong số ít dạng tài liệu sống mãi cùng mã nguồn. GitHub hay các dạng tập trung khác không phải là định dạng dữ liệu mở để mọi người dễ dàng sao lưu, chuyển đổi, di chuyển; nên khi chuyển dự án đi, người ta thường bỏ dữ liệu lại phía sau.
      Vì vậy hiện tại nó có thể không giúp ích nhiều cho cộng đồng, nhưng sẽ có ích cho người gỡ lỗi vài năm sau.
  • Tôi đồng ý với mục đích tổng thể, nhưng sẽ tốt hơn nếu đặt một BLUF cụ thể hơn ở đầu. Ví dụ viết kiểu “Fix test issues caused by non-breaking space character \xa0”
    Có thể hiểu ngay vấn đề là gì, và nếu muốn biết thêm thì vẫn có quyền đọc phần bên dưới

    • Tôi thấy thông điệp này tốt hơn nhiều. Nếu xem diff trên GitHub thì cũng khá rõ cái gì đã thay đổi. Vì nếu một changeset trông y hệt nhau trong diff, gần như chỉ có trường hợp ký tự vô hình được thêm vào hoặc bị xóa đi
      Vì vậy, để tìm kiếm trong lịch sử thì chỉ cần một thông điệp dòng đầu tốt là đủ. Tôi thấy câu chuyện ngắn về việc đi đến tận Narnia rồi quay về để tìm nguyên nhân gốc của bug không liên quan lắm. Tuy vậy, tôi cũng không phản đối việc viết nó vào phần mô tả PR hoặc phần thông điệp mở rộng của commit như một cách xả bực
    • Thông điệp commit lý tưởng cũng chỉ đến mức đó. Phần còn lại trong bài chỉ là câu chuyện về cách phát hiện ra nó. Tôi không nghĩ nội dung giải thích quá trình làm việc cần nằm trong thông điệp commit Git. Thông điệp đó cho biết vì sao và thay đổi gì đã được thực hiện, như vậy là đủ
    • Tôi thích khái niệm này. Luôn đặt nội dung có thể hành động nhất hoặc quan trọng nhất ở trên cùng, rồi sau đó mới đến bối cảnh. Phải tôn trọng thời gian của người khác và đừng chôn vùi ý chính
  • Tôi từng cảm thấy tự hào khi viết được một thông điệp commit xuất sắc, nhưng ít chắc chắn hơn về giá trị nó mang lại cho người khác. Khi gặp một thông báo lỗi lạ, thêm tính năng mới, hoặc gần như trong bất kỳ tình huống nào, tôi nghĩ đa số mọi người không tìm kiếm trong thông điệp commit
    Hơi buồn, nhưng tôi ngày càng nghi ngờ rằng những thông điệp commit đẹp đẽ có phần giống sự phù phiếm của lập trình viên. Người chủ yếu trầm trồ là chính tác giả, còn người khác thì lướt qua mà không nhận ra
    Đôi khi vẫn có chỗ cho kiểu trang trí thẩm mỹ đó, nhưng tôi không chắc nó có giá trị thực dụng lớn. Giờ nếu người khác commit với nội dung “fix whitespace issue” thì tôi cũng không còn quá bận tâm nữa, và nhờ vậy có lẽ tôi đã trở thành một đồng nghiệp tốt hơn
    Với các dự án có đội ngũ phân tán khổng lồ và vô số commit như Git hay Linux thì có thể khác. Những dự án tôi quen thuộc thường có 1–100 người đóng góp và phần lớn thuộc cùng một tổ chức

    • Thông điệp commit vẫn có giá trị ngay cả khi người duy nhất xem nó suốt đời là chính bạn. Khi tìm kiếm nhị phân một vấn đề, thông điệp của commit cuối cùng tìm ra được thực sự hữu ích. Nó còn hữu ích hơn nếu không chỉ là “fixed thing”. Điều đó cũng có nghĩa là khi gặp lại vấn đề tương tự, bạn có ghi chú commit để tra cứu
    • Nghe có thể lạ, nhưng với các dự án tôi tham gia tích cực, tôi cố gắng ít nhất lướt qua mọi commit. Nếu là dự án mã nguồn mở, thông điệp commit đó sẽ tồn tại mãi mãi, và có thể được lập chỉ mục không chỉ trong tìm kiếm mã mà cả các công cụ tìm kiếm thông thường. Tuy nhiên, giờ GitHub ngày càng chặn bot nhiều hơn nên có thể điều này ít đúng hơn
      Khi Google hay Stack Overflow không cho ra đáp án, tôi cũng tìm trên GitHub xem có nội dung tương tự trong PR hoặc thông điệp commit không. Tính cả các kho riêng tư mà tôi có quyền truy cập, tôi đã được giúp vô số lần. Thông điệp commit tốt chắc chắn có giá trị vượt xa sự phù phiếm. Nếu nhiều lập trình viên không xem chúng thì đó là thiệt thòi của họ, và hy vọng khi tích lũy kinh nghiệm, một ngày nào đó họ sẽ nhận ra. Cũng có thể dạy lập trình viên junior cách tìm kiếm hoặc gửi bài gốc cho họ
    • Tôi đã vài lần bị hại bởi thông điệp commit quá ngắn. Kiểu như khi ai đó hỏi “tại sao lại làm thế này?”, tôi kiểm tra lịch sử Git và phát hiện thông điệp do chính mình để lại 3 năm trước là “it should be done this way”
      Từ đó về sau, tôi cố viết thông điệp commit sao cho ít nhất bản thân trong tương lai có thể nhớ ra vì sao thay đổi đó là cần thiết
    • Nếu trước khi sửa một dòng code mà bạn không chạy git blame thì bạn đang làm sai
      Nhiều lần, khi tôi định sửa một bug rõ ràng, ngay trước lúc commit tôi xem lại commit trước đó và phát hiện “bug” đó được đưa vào có chủ ý, còn task JIRA liên kết thì giải thích rất rõ vì sao thay đổi tưởng như hiển nhiên của tôi sẽ tái tạo một bug từ 2 năm trước
    • Tôi thường dùng chức năng git blame trong IDE để nắm chuyện gì đã xảy ra. Khi gặp một thông điệp commit tốt, tôi thấy biết ơn
  • Dòng đầu của thông điệp commit là quan trọng nhất vì nó giúp git log xử lý hàng rào Chesterton. Trong trường hợp này, tôi nghĩ tác giả đã vung hụt
    Điểm mấu chốt là dòng đầu nên nói vì sao làm, chứ không phải đã làm gì. Ai quan tâm cái gì đã thay đổi thì có thể xem code hoặc diff
    Ví dụ có thể viết “nginx .conf files must be in us-ascii”, rồi tiếp theo là “changed blahblah.erb to remove nonbreaking space character”, sau đó nối tiếp phần còn lại của thông điệp commit vốn khá tốt
    Nên nghĩ như một bài báo. Hãy giả định độc giả có thể dừng đọc ở bất kỳ điểm nào, và viết theo thứ tự mức độ quan trọng giảm dần, còn chi tiết tăng dần

    • Dòng đầu trước hết nên tóm tắt đã thay đổi gì để có thể tìm ra commit có vấn đề
      Bài báo cũng giải thích cái gì ở tiêu đề, chứ không phải vì sao
      Trong trường hợp này, dòng đầu của bản gốc là vừa đúng. Khi lướt git log, bạn có thể đoán commit này nhiều khả năng không thay đổi hành vi chức năng của test và bỏ qua
    • Thông điệp commit của một dự án bất kỳ không phải là nơi để dạy ai đó quy tắc của nginx
      “nginx .conf files must be in us-ascii” có thể là tiêu đề bug hoặc PR tốt, nhưng nó cũng có thể tương ứng với nhiều commit làm các việc khác nhau, và không cho biết thực sự chuyện gì đã xảy ra. Không biết đó là chuyển file sang US-ASCII, tạo công cụ chuyển đổi, cập nhật tài liệu, tạo test, hay một tổ hợp các việc đó. Bắt đầu bằng cái gì thay vì vì sao sẽ giảm sự mơ hồ đó
    • Có lẽ chỉ cần nói rằng vì có trường hợp chỉ dòng đầu được hiển thị, nên hãy đặt nội dung có nghĩa vào dòng đầu là được
      “The files must be in us-ascii” hay “Changed the files to us-ascii” cũng không khác nhau nhiều. Cả hai đều cho biết rõ rằng các file đã được đổi sang US-ASCII
  • Nhược điểm của cách tài liệu hóa này là thông điệp commit một khi đã viết thì về thực chất không thể sửa được
    Tất nhiên có thể làm bằng rebase, nhưng liệu có thật sự muốn sửa một nội dung đã viết từ 1 năm trước và đã được merge vào main, gây đau khổ cho các nhánh tính năng của mọi người không
    So với tài liệu lưu trong file .md, Wiki hay Confluence, tôi có thể cải thiện nội dung đồng nghiệp viết, và đồng nghiệp khác cũng có thể cải thiện nội dung tôi viết
    Trong trường hợp này, lỗi có thể đã được sửa và không xuất hiện lại. Nhưng khi commit một component cụ thể, có cám dỗ muốn giải thích thiết kế của nó, và giờ tôi tránh làm vậy. Nếu sau này component đó thay đổi vì yêu cầu kinh doanh đổi khác thì sao. Tài liệu trong commit có chỉ còn giải thích phần khác biệt không. Khi đó thành viên mới muốn hiểu hệ thống sẽ phải đọc nhiều thông điệp commit rồi tự merge chúng trong đầu

    • Đó không phải là nhược điểm. Commit là ghi chép lịch sử, nên khi quay lại sau 3 năm, ta muốn biết mục đích của nó trong bối cảnh lúc đó là gì, chứ không muốn xem một lịch sử đã được tẩy rửa
      So sánh với file .md, Wiki hay Confluence chẳng khác nào so sánh xe đạp với con ngỗng
      Những cân nhắc hay đánh đổi ở thời điểm tạo component, hoặc việc không hề có những thứ đó, thường hữu ích để hiểu lỗi gốc, các tiến hóa về sau, và những khiếm khuyết phát sinh từ thay đổi trong use case
      Nếu thành viên mới muốn hiểu hệ thống thì chỉ cần duy trì một tài liệu “hiện tại” riêng. Tài liệu đó không cần đề cập cả các đánh đổi trong triển khai hay chuyện bản nháp được viết dưới áp lực thời gian
    • Tôi cho rằng việc thông điệp commit không thể chỉnh sửa lại là một lợi thế. Việc sửa sau này thì khó, nhưng theo dõi lịch sử codebase từng bước một thật sự phơi bày ra rất nhiều điều
    • Thông điệp commit không phải là tài liệu cần được cập nhật theo thời gian, mà là ghi chép lịch sử của một thay đổi đơn lẻ. Sau này nhận ra mình đã bỏ sót một chi tiết quan trọng thì đáng tiếc, nhưng nhìn tổng thể, tôi nghĩ điều quan trọng là nó tuyệt đối không thay đổi
    • Tôi cho rằng sai lầm của Git là đã trộn lẫn một log bất biến về những gì đã thay đổi với một câu chuyện, lý tưởng là có thể thay đổi, về những gì đã được merge. Vì vậy mới nảy sinh tranh luận về squash commit, rebase và merge
      Squash commit giúp bản ghi tốt hơn như một câu chuyện về việc thêm tính năng, merge bảo toàn log bất biến của thay đổi code thực tế, còn rebase thì làm mỗi thứ một chút
      Không có lý do gì lại không thể có cả hai. Chúng ta là những người lập trình máy tính, nên có thể tạo ra thứ mình muốn
      Nếu viết lại Git từ đầu, tôi sẽ chia commit thành hai phần. Lịch sử thay đổi sẽ được giữ bất biến bằng cấu trúc kiểu Merkle DAG như Git, còn thông điệp commit sẽ được lưu trong một kho dữ liệu liên kết riêng, thành một log hợp lý và có thể chỉnh sửa để mô tả workflow. Có thể nhóm commit theo tag tính năng, sửa lỗi chính tả, thay đổi thông điệp tùy ý, nhưng vẫn giữ nguyên log diff bên dưới, tức “những gì thật sự đã thay đổi trong code”
    • Có thể bổ sung bằng git notes. Tuy nhiên nếu thông điệp dài đến vậy thì có vẻ ít khả năng có ai nhận ra
  • Có một điểm tôi không đồng ý. Đó là đoạn “không kỳ vọng mức độ chi tiết như thế này ở mọi commit, đặc biệt là commit cỡ này”
    Theo kinh nghiệm của tôi, ngược lại, những thứ nhỏ và trông vô hại thường lại cần phần giải thích tương đối dài hơn
    Hôm qua tôi đã viết ba đoạn để giải thích vì sao thêm --limit=999 vào gh pr list. Vì nó dễ gây nhầm lẫn. Ngay trong đối số --jq đã có limit(, và nếu giả định tổng số PR là vô hạn, thì giá trị càng cao kết quả cuối cùng thực ra lại càng thấp
    Tôi cũng viết comment trong code, và có lẽ thời gian suy nghĩ, trau chuốt còn lâu hơn thời gian viết. Mong rằng đây sẽ được nhớ như một ví dụ tiếp theo mỗi khi ai đó ám chỉ công việc này chỉ là bắn code ào ào

    • Tôi đồng ý rằng những thứ nhỏ và trông vô hại cần giải thích dài hơn, nhưng thông điệp commit được liên kết thì quá dài. Nó làm phí thời gian của người đọc, hoặc khiến mắt họ lướt mờ đi trước một bức tường chữ. Không cần ghi lại toàn bộ hành trình chỉ để tài liệu hóa điều đã phát hiện và lý do
      “This was a non-ascii whitespace character that caused ArgumentError: invalid byte sequence in US-ASCII when running bundle exec rake” là đủ. Có từ khóa để sau này tìm các vấn đề tương tự, có nguyên nhân gốc, và không quá dài nên ít có khả năng bị mọi người lướt qua
    • Nếu là commit thêm binding cho một ngôn ngữ, dù thêm/xóa hơn 100 dòng thì vẫn có thể chỉ viết cỡ “Add X function”. Vì nó chỉ làm theo một mẫu đã được xác lập. Nhưng với loại thay đổi trong liên kết thì giải thích nhiều đoạn chắc chắn hữu ích
    • Comment trong code cũng thường được viết theo mẫu tương tự. Với những phần lõi nhỏ của code “thú vị”, tỷ lệ comment so với code có thể từ 1:1 trở lên, và nhờ vậy phần còn lại của codebase có thể được giữ là những đoạn boilerplate nhàm chán, tự giải thích, không cần nhiều comment
  • Tôi không nghĩ đây là một Git commit xuất sắc
    So với lượng văn bản kia, dòng đầu “Convert template to US-ASCII to fix error” có thể tốt hơn. Chỉ cần thêm vài từ nói ký tự khoảng trắng nào gây lỗi và lỗi là gì. Chỉ riêng phần giải thích đó cộng với diff đã đủ bối cảnh cần thiết
    Thành thật mà nói, phần còn lại gần như vô dụng. Nó không gây hại, nhưng giá trị cũng không lớn. Tác giả đã tài liệu hóa hành trình truy vết lỗi này, nhưng tôi tự hỏi ai sẽ quan tâm

    • Những người muốn học hỏi và trở thành lập trình viên giỏi hơn sẽ quan tâm. Thực tế bài viết đang giải thích giá trị của phần bổ sung đó, nghĩa là có người quan tâm
      Trong bài còn có liên kết kết quả tìm kiếm cho thấy nhiều commit do những người đã học được từ bản sửa đó để lại
      Thông điệp commit đó là một kho tri thức
  • Muốn xem thông điệp commit xuất sắc thì hãy xem lịch sử Git của nhân Linux. Ở đó, đây là tiêu chuẩn
    Dòng đầu luôn nhắc đến subsystem bị ảnh hưởng bởi thay đổi, rồi tiếp theo là một tóm tắt một dòng ở thể mệnh lệnh. Sau đó trả lời ba câu hỏi càng chi tiết càng tốt

    1. Hành vi hiện tại là gì
    2. Điều gì dẫn đến thay đổi này
    3. Hành vi mới sau khi áp dụng thay đổi là gì
      Ví dụ có thể viết như: “Code hiện tại làm X. Khi chạy test case T, quan sát thấy hành vi ngoài dự kiến U. Điều này là do lý do R. Sửa bằng cách làm F”
  • Gần đây có một người đóng góp nói rằng cách tôi viết thông điệp Git, tức các yêu cầu của tôi, là “độc đáo”. Có vẻ nền tảng Linux kernel của tôi đã lộ ra, nhưng tất cả thông điệp commit của tôi đều trông như trong bài này
    Nếu là nội dung liên quan đến mã hiện có, phần chú thích nên đi cùng mã. Những nội dung liên quan đến quy trình, chẳng hạn như mã đã bị xóa hoặc mã từng không hoạt động, nên nằm trong commit
    Điều quan trọng nhất là thông điệp commit có thể tham chiếu đến issue cho tiện, nhưng nhất định phải tái hiện các chi tiết cốt lõi. GitHub chỉ mang tính tạm thời, còn thông điệp Git thì không

  • Một thông điệp commit đầy đủ ngữ cảnh có ở đây[1]
    Chuyện này phổ biến đến mức maintainer đã viết bài này[2]
    [1] https://github.com/git/git/commit/d70f554cdf38b0b05cfaa8e8eb...
    [2] https://lore.kernel.org/git/xmqqedevo8ps.fsf@gitster.g/