Kiểm soát phiên bản nâng cao với Git
Git là một phần mềm kiểm soát phiên bản rất phổ biến. Trước đó có những cái phổ biến khác như Subversion, và trước đó nữa như CVS, … Điều đặc biệt ở Git là nó theo mô hình phân bố (distributed).
Ví dụ: Mọi nhà phát triển đều có thể có bản sao cục bộ của toàn bộ kho lưu trữ vì vậy nó có thể hoạt động độc lập trên đó. Và mỗi kho lưu trữ cục bộ local repo cũng có thể có các nhánh riêng không được đồng bộ hóa với các kho lưu trữ từ xa. Và nếu chúng ta cần thì vẫn có thể đồng bộ hóa chúng.
Git là một công cụ rất quan trọng đối với cộng đồng mã nguồn mở nói chung. Linux là một trong những dự án mã nguồn mở lớn đã được chuyển sang Git rất nhanh. Vậy các khối xây dựng quan trọng của Git là gì?
Với Git bạn sẽ có một thư mục làm việc, thư mục này là thư mục mà bạn làm việc với mã nguồn. Vì vậy nếu bạn muốn làm việc trên bất kì mã nào, bạn thường tạo, sao chép, kiểm tra thứ gì đó từ kho lưu trữ bên trong thư mục làm việc của bạn.
Bên trong thư mục làm việc đó sẽ chứa các file của bạn. Thông thường, những file đó có thể được theo dõi hoặc không được theo dõi. Git sẽ không quan tâm đến các file đó có được theo dõi hay không. Vì vậy khi bạn muốn làm việc với chúng, về cơ bản bạn sẽ nói với Git rằng “những file này quan trọng đối với tôi”. Ví dụ, bạn có một file chưa được sửa đổi, khi bạn sửa đổi file này bạn cần sử dụng lệnh git add để đưa nó vào vùng staging.
Vùng đệm staging chứa danh sách các đối tượng mà bạn muốn đẩy vào kho lưu trữ trong lần commit tiếp theo. Và khi bạn thực hiện git commit, bạn chỉ định ai là người chịu trách nhiệm, mục đích của việc commit đó là gì? Và sau đó điều này được lưu trữ trong kho lưu trữ cục bộ.
Vì vậy, cho đến thời điểm này, mọi thay đổi bạn thực hiện đều được theo dõi. Bạn có thể thấy những gì đã được thay đổi, khi nào, như thế nào, ai đã làm điều đó, ... Nhưng nó không được đồng bộ với vị trí từ xa. Vì vậy, khi bạn muốn đồng bộ hóa kho lưu trữ cục bộ của mình với kho lưu trữ từ xa, bạn cần sử dụng git fetch, git push, git pull còn nếu không bạn chỉ có bản sao cục bộ.
Tất nhiên, vì bạn có kho lưu trữ cục bộ, điều bạn cần làm là kiểm tra kho lưu trữ cục bộ đó, bạn sẽ sử dụng lệnh git checkout. Đây là snapshot, mọi thứ có mặt tại thời điểm đó, bạn có nó trong thư mục làm việc của mình. Và khi có các thay đổi bạn có thể thực hiện git merge để tích hợp các thay đổi của mình với một số thay đổi khác.
Bởi vì Git đang theo dõi các file nên Git sẽ biết trạng thái snapshot đó là gì. Sau đó nó có thể tích hợp những thay đổi đó một cách tự động. Ví dụ, nếu nhiều người dùng đang thay đổi cùng một file nhưng ở các dòng code khác nhau chẳng hạn, thì Git có thể hợp nhất các thay đổi đó một cách tự động mà không xảy ra bất kỳ xung đột nào. Nhưng khi người dùng đang thay đổi các dòng giống nhau, thì ai đó cần phải xem lại những thay đổi đó và cuối cùng cần đưa ra quyết định sẽ lấy thay đổi nào làm thay đổi cuối.
Và khi điều này được giải quyết, nó có thể được đẩy vào kho lưu trữ từ xa để các nhà phát triển khác cũng có thể lấy được. Khác với Git thì Subversion theo kiểu tập trung, nơi mà việc di chuyển kho lưu trữ khá khó khăn, tất nhiên với Git thì nó là một phần của thiết kế mà bạn có nhiều bản sao của kho lưu trữ. Kho lưu trữ bao gồm tất cả các đối tượng, lịch sử và những thay đổi trên các đối tượng đó.
Vậy Git hoạt động như thế nào? Một phần quan trọng của Git chính là con trỏ. Con trỏ là một đại diện của đối tượng Git và bạn có nhiều loại đối tượng Git. Đầu tiên là Blob, Blob có thể là bất cứ thứ gì. Bạn có thể lưu trữ file đa phương tiện, file nhị phân, file văn bản hoặc bất cứ file gì khác, Git sẽ không quan tâm nó là gì. Vì vậy, đây chỉ là một biểu diễn của dữ liệu trên thiết bị lưu trữ.
Sau đó, bạn sẽ có một sơ đồ cây chứa danh sách các con trỏ đến các Blobs đó. Nó cũng có thể trỏ đến các cây con khác. Vì vậy, trong sơ đồ cây, bạn biết ai là gốc và ai là ngọn từ đó Git có thể hiển thị cho bạn những gì đã thay đổi giữa các trạng thái snapshot khác nhau.
Và cuối cùng là Commit. Về cơ bản, commit có rất nhiều dữ liệu, nó có siêu dữ liệu thông tin về snapshot liên quan đến ai, ai đã thực hiện thay đổi, thay đổi là gì, thông báo văn bản về change-- vì vậy đây là thứ thường là một phần của nhật ký log-- và thuộc nhánh nào của sơ đồ cây.
Git là một phần mềm kiểm soát phiên bản rất phổ biến. Trước đó có những cái phổ biến khác như Subversion, và trước đó nữa như CVS, … Điều đặc biệt ở Git là nó theo mô hình phân bố (distributed).
Ví dụ: Mọi nhà phát triển đều có thể có bản sao cục bộ của toàn bộ kho lưu trữ vì vậy nó có thể hoạt động độc lập trên đó. Và mỗi kho lưu trữ cục bộ local repo cũng có thể có các nhánh riêng không được đồng bộ hóa với các kho lưu trữ từ xa. Và nếu chúng ta cần thì vẫn có thể đồng bộ hóa chúng.
Git là một công cụ rất quan trọng đối với cộng đồng mã nguồn mở nói chung. Linux là một trong những dự án mã nguồn mở lớn đã được chuyển sang Git rất nhanh. Vậy các khối xây dựng quan trọng của Git là gì?
Với Git bạn sẽ có một thư mục làm việc, thư mục này là thư mục mà bạn làm việc với mã nguồn. Vì vậy nếu bạn muốn làm việc trên bất kì mã nào, bạn thường tạo, sao chép, kiểm tra thứ gì đó từ kho lưu trữ bên trong thư mục làm việc của bạn.
Bên trong thư mục làm việc đó sẽ chứa các file của bạn. Thông thường, những file đó có thể được theo dõi hoặc không được theo dõi. Git sẽ không quan tâm đến các file đó có được theo dõi hay không. Vì vậy khi bạn muốn làm việc với chúng, về cơ bản bạn sẽ nói với Git rằng “những file này quan trọng đối với tôi”. Ví dụ, bạn có một file chưa được sửa đổi, khi bạn sửa đổi file này bạn cần sử dụng lệnh git add để đưa nó vào vùng staging.
Vùng đệm staging chứa danh sách các đối tượng mà bạn muốn đẩy vào kho lưu trữ trong lần commit tiếp theo. Và khi bạn thực hiện git commit, bạn chỉ định ai là người chịu trách nhiệm, mục đích của việc commit đó là gì? Và sau đó điều này được lưu trữ trong kho lưu trữ cục bộ.
Vì vậy, cho đến thời điểm này, mọi thay đổi bạn thực hiện đều được theo dõi. Bạn có thể thấy những gì đã được thay đổi, khi nào, như thế nào, ai đã làm điều đó, ... Nhưng nó không được đồng bộ với vị trí từ xa. Vì vậy, khi bạn muốn đồng bộ hóa kho lưu trữ cục bộ của mình với kho lưu trữ từ xa, bạn cần sử dụng git fetch, git push, git pull còn nếu không bạn chỉ có bản sao cục bộ.
Tất nhiên, vì bạn có kho lưu trữ cục bộ, điều bạn cần làm là kiểm tra kho lưu trữ cục bộ đó, bạn sẽ sử dụng lệnh git checkout. Đây là snapshot, mọi thứ có mặt tại thời điểm đó, bạn có nó trong thư mục làm việc của mình. Và khi có các thay đổi bạn có thể thực hiện git merge để tích hợp các thay đổi của mình với một số thay đổi khác.
Bởi vì Git đang theo dõi các file nên Git sẽ biết trạng thái snapshot đó là gì. Sau đó nó có thể tích hợp những thay đổi đó một cách tự động. Ví dụ, nếu nhiều người dùng đang thay đổi cùng một file nhưng ở các dòng code khác nhau chẳng hạn, thì Git có thể hợp nhất các thay đổi đó một cách tự động mà không xảy ra bất kỳ xung đột nào. Nhưng khi người dùng đang thay đổi các dòng giống nhau, thì ai đó cần phải xem lại những thay đổi đó và cuối cùng cần đưa ra quyết định sẽ lấy thay đổi nào làm thay đổi cuối.
Và khi điều này được giải quyết, nó có thể được đẩy vào kho lưu trữ từ xa để các nhà phát triển khác cũng có thể lấy được. Khác với Git thì Subversion theo kiểu tập trung, nơi mà việc di chuyển kho lưu trữ khá khó khăn, tất nhiên với Git thì nó là một phần của thiết kế mà bạn có nhiều bản sao của kho lưu trữ. Kho lưu trữ bao gồm tất cả các đối tượng, lịch sử và những thay đổi trên các đối tượng đó.
Vậy Git hoạt động như thế nào? Một phần quan trọng của Git chính là con trỏ. Con trỏ là một đại diện của đối tượng Git và bạn có nhiều loại đối tượng Git. Đầu tiên là Blob, Blob có thể là bất cứ thứ gì. Bạn có thể lưu trữ file đa phương tiện, file nhị phân, file văn bản hoặc bất cứ file gì khác, Git sẽ không quan tâm nó là gì. Vì vậy, đây chỉ là một biểu diễn của dữ liệu trên thiết bị lưu trữ.
Sau đó, bạn sẽ có một sơ đồ cây chứa danh sách các con trỏ đến các Blobs đó. Nó cũng có thể trỏ đến các cây con khác. Vì vậy, trong sơ đồ cây, bạn biết ai là gốc và ai là ngọn từ đó Git có thể hiển thị cho bạn những gì đã thay đổi giữa các trạng thái snapshot khác nhau.
Và cuối cùng là Commit. Về cơ bản, commit có rất nhiều dữ liệu, nó có siêu dữ liệu thông tin về snapshot liên quan đến ai, ai đã thực hiện thay đổi, thay đổi là gì, thông báo văn bản về change-- vì vậy đây là thứ thường là một phần của nhật ký log-- và thuộc nhánh nào của sơ đồ cây.