1 == Thủ Thuật Tạo Nhánh ==
3 Tạo Nhánh và Trộn là các đặc tính sát thủ của Git.
5 *Vấn đề đặt ra*: Những nhân tố bên ngoài chắc hẳn đòi hỏi cần hoán chuyển văn cảnh. Một lỗi tồi tệ
6 xuất hiện trong phiên bản đã được phát hành mà không được cảnh báo gì. Điều tồi tệ nhất có thể xảy ra
7 là phải xóa bỏ hẳn đặc tính kỹ thuật đó. Người phát triển phần mềm, người mà đã giúp bạn viết nó, cần biết lý do về việc bãi bỏ. Trong tất cả các trường hợp trên, bạn buộc phải xóa bỏ cái mà bạn đang làm và làm một cái hoàn toàn mới.
9 Việc gán đoạn suy nghĩ có thể làm giảm hiệu suất làm việc, và việc hoán chuyển nội dung càng cồng kềnh, vướng víu càng gây hậu quả nặng nề. Đối với các hệ thống quản lý mã nguồn tập trung chúng ta phải tải về một bản sao các tập tin mới từ máy chủ trung tâm. Các hệ thống phân tán hoạt động hiệu quả hơn, như là chúng ta có thể nhân bản một cách cục bộ.
11 Nhưng việc nhân bản bắt buộc phải sao chép toàn bộ thư mục làm việc cũng như là toàn bộ các mục trong lịch sử cho đến thời điểm đã được chỉ ra. Dù là Git giảm bớt sự lãng phí cho việc này bằng cách chia sẻ và tạo ra các liên kết tập tin cứng, chính bản thân các tập tin dự án cũng phải được tạo ra trong các đề mục của chúng trong thư mục làm việc.
13 *Giải pháp*: Git có một công cụ tốt hơn để sử lý tình huống này, nó nhanh và tiết kiệm không gian lưu trữ hơn lệnh nhân bản đó chính là: *git branch*.
15 Với vài câu thần chú, các tập tin trong thư mục của bạn dễ dàng biến đổi từ phiên bản này sang phiên bản khác. Sự chuyển đổi này có thể làm nhiều hơn việc di chuyển trong trong lịch sử một các đơn thuần. Các tập tin của bạn có thể chuyển hình thái từ bản phát hành cuối thành phiên bản thử nghiệm, thành phiên bản phát triển hiện nay, thành phiên bản của người bạn của bạn, và cứ như thế.
17 === Nút Điều Khiển ===
19 Mỗi khi chơi điện tử, bạn bấm vào nút (``nút điều khiển''), màn hình có lẽ hiển thị ngay ra một cái bảng hay một thứ gì đó? Thế thì nhỡ ông chủ của bạn đang đi lại trong văn phòng nơi bạn đang chơi điện tử thì làm cách nào để nhanh chóng giấu chúng đi?
23 $ echo "Tôi thông minh hơn xếp của mình" > myfile.txt
26 $ git commit -m "Lần commit đầu tiên"
28 Chúng ta đã tạo ra kho chứa Git mà nó theo dõi một tập tin văn bản có chứa một thông điệp đã biết trước. Giờ hãy gõ:
30 $ git checkout -b boss # dường như chẳng có gì thay đổi sau lệnh này
31 $ echo "Xếp thông minh hơn tôi" > myfile.txt
32 $ git commit -a -m "Lần chuyển giao khác"
34 Điều này cũng giống như việc chúng ta ghi đè lên tập tin của mình sau đó commit nó. Nhưng không, đó chỉ là ảo tưởng. Gõ:
36 $ git checkout master # quay trở lại phiên bản nguyên gốc của tập tin
38 Ối trời ơi! Tập tin văn bản lại trở về như cũ mất rồi. Và nếu ông chủ có ý định ngó qua thư mục của bạn thì hãy gõ:
40 $ git checkout boss # chuyển trở lại phiên bản vừa mắt ông chủ
42 Bạn có thể hoán chuyển giữa hai phiên bản của tập tin tùy thích, và commit từng cái trong số chúng một cách độc lập.
47 Bạn nói rằng mình đang làm việc với một số đặc tính kỹ thuật, và vì lý do nào đó, bạn muốn quay trở lại bản cách đây ba bản và tạm thời đặt thêm vài dòng lệnh
48 in ra màn hình để có thể thấy được một số hàm hoạt động như thế nào. Thế thì:
53 Giờ thì bạn có thể thêm những dòng mã lệnh tạm thời ở đâu mình muốn. Bạn còn có thể commit những thay đổi đó. Khi bạn đã làm xong, hãy thực hiện lệnh
57 để quay lại công việc chính. Chú ý là bất kỳ các thay đổi không được commit sẽ đổ xuống sông xuống biển.
59 Nhưng bạn lại muốn ghi lại các thay đổi tạm thời đó sau khi đã làm xong? Rất dễ:
61 $ git checkout -b dirty
63 và commit trước khi quay trở lại nhánh master. Khi nào đó bạn muốn quay trở lại các thay đổi ở trên, đơn giản, chỉ cần gõ:
67 Chúng ta đã đụng chạm đến lệnh như trên ở những chương trước rồi, khi thảo luận về việc tải về một trạng thái cũ. Cuối cùng chúng ta có thể thuật lại toàn bộ câu chuyện: các tập tin đã thay đổi theo trạng thái đã được yêu cầu, nhưng chúng ta phải rời bỏ nhánh master. Tất cả những lần commit được tạo ra từ đây sẽ dẫn bạn đi trên một nhánh khác, nhánh này có thể được đặt tên sau.
69 Mặt khác, sau khi 'check out' một trạng thái cũ, Git tự động đặt bạn vào một trạng thái mới, một nhánh chưa có tên, và nhánh này có thể đặt tên và ghi lại với lệnh *git checkout -b*.
73 Bạn đang phân vân giữa ngã ba đường khi bạn phải quyết định là xóa tất cả mọi thứ hoặc là sửa chữa các lỗi mới phát hiện ra trong lần commit `1b6d...`:
76 $ git checkout -b fixes 1b6d # checkout và đặt tên là nhánh fixes
78 Sau khi hoàn tất việc sửa chữa:
80 $ git commit -a -m "Đã sửa"
83 và sau đó quay lại công việc theo phận sự của mình. Bạn thậm chí có thể trộn với lần commit đã sửa để
90 Với một số hệ thống quản lý mã nguồn, việc tạo các nhánh rất dễ dàng nhưng trộn chúng
91 trở lại là một bài toán hóc búa. Với Git, việc trộn là dễ dàng và bạn có thể
92 không hay biết nó hoạt động như thế nào.
94 Chúng ta đã sử dụng việc trộn từ lâu rồi. Lệnh *pull* trên thực tế đã 'fetch' (lấy về)
95 các lần commit và sau đó trộn chúng vào trong nhánh hiện hành của bạn. Nếu trên máy của mình bạn không có
96 thay đổi gì cả, thế thì việc trộn sẽ là một 'fast forward' (chuyển tiếp nhanh), trường hợp này cũng na ná như việc lấy về
97 phiên bản cuối cùng trong hệ thống quản lý mã nguồn tập trung. Nhưng nếu bạn đã có thay đổi
98 trên máy của mình, Git sẽ tự động trộn, và báo lỗi cho bạn nếu có xung đột xảy ra.
100 Thông thường, mỗi lần commit có một 'commit cha', tạm gọi thế, chính là lần
101 commit trước. Việc trộn các nhánh với nhau phát sinh ra một lần commit với ít nhất hai 'cha'.
102 Điều này đặt ra câu hỏi: lần commit mà `HEAD~10` thực sự ám chỉ đến là lần nào? Một lần commit
103 có thể có nhiều cha, thế thì chúng ta phải theo cái nào?
105 Nó sẽ gọi ra 'cha' đầu tiên. Đây là
106 điều ta mong muốn bởi vì nhánh hiện hành trở thành cha đầu tiên trong suốt quá trình trộn;
107 thường, bạn chỉ liên quan đến những thay đổi mình tạo ra trong nhánh
108 hiện hành, cốt để mà đối lập với việc trộn thay đổi từ các nhánh khác.
110 Bạn hãy nhớ Git quy một cha nào đó với một dấu mũ. Ví dụ, để hiển thị
111 nhật ký tính từ 'cha' thứ hai:
115 Bạn có thể bỏ qua số dành cho cha đầu tiên. Ví dụ, để hiển thị
116 sự khác nhau với cha đầu tiên:
120 Bạn có thể tổ hợp các dấu mũ này với các kiểu khác nhau. Ví dụ:
122 $ git checkout 1b6d^^2~10 -b ancient
124 bắt đầu một nhánh mới ``ancient'' tương ứng với trạng thái lần commit thứ 10 trở về trước từ
125 cha thứ hai của cha thứ nhất của lần commit bắt đầu với 1b6d.
127 === Làm Việc Liên Tục ===
129 Thường trong các dự án phần cứng, bước thứ hai của kế hoạch phải chờ bước thứ nhất hoàn thành. Một chiếc xe hơi cần sửa chữa có thể phải nằm chờ trong xưởng sửa chữa cho đến khi các chi tiết phụ tùng đặc biệt được chuyển đến từ nhà máy. Một mẫu có thể phải chờ một con chip được làm ra trước khi quá trình chế tác có thể tiếp tục.
131 Dự án phần mềm cũng có thể tương tự như thế. Bộ phận thứ hai có một số tính năng có thể phải
132 chờ cho đến khi phần thứ nhất đã được phát hành và kiểm tra. Một số dự án yêu cầu
133 mã nguồn của bạn phải được xem xét lại trước khi chấp nhận nó, vì vậy bạn có thể phải chờ cho đến khi bộ phận
134 thứ nhất đã được chấp thuận trước khi bắt đầu phần thứ hai.
136 Nhờ có việc tạo nhánh và trộn dễ dàng và cũng chẳng mất mát gì, chúng ta có thể phá vỡ quy tắc và làm việc trên
137 Part II trước khi Part I chính thức sẵn sàng. Giả sử bạn đã commit Part I
138 và gửi nó đi để xem xét. Giả sử bạn đang ở nhánh `master`. Thế thì hãy phân nhánh
141 $ git checkout -b part2
143 Tiếp đến, làm việc trên Part II, commit những thay đổi của bạn bao nhiêu tùy thích. Lỗi là ở con người,
144 và bạn sẽ phải thường xuyên quay trở lại để sửa lỗi nào đó trong Part I.
145 Nếu may mắn, hay trong trường hợp tốt, bạn có thể bỏ qua những dòng này.
147 $ git checkout master # Quay trở lại Part I.
149 $ git commit -a # Commit sau khi sửa lỗi.
150 $ git checkout part2 # Quay trở lại Part II.
151 $ git merge master # Trộn các thay đổi.
153 Cuối cùng, Part I được chấp thuận:
155 $ git checkout master # Quay trở lại Part I.
156 $ submit files # Xuất bản ra!
157 $ git merge part2 # Trộn vào Part II.
158 $ git branch -d part2 # Xóa nhánh "part2".
160 Bây giờ chúng ta lại ở trong nhánh `master`, với Part II trong thư mục làm việc.
162 Thủ thuật này rất dễ dàng để mở rộng ra dành cho nhiều phần hơn. Nó cũng đễ dàng để
163 phân nhánh ra từ quá khứ: giả sử muộn bạn mới nhận ra là mình phải tạo
164 một nhánh từ trước đây 7 lần commit. Thế thì gõ:
166 $ git branch -m master part2 # Đổi tên nhánh "master" thành "part2".
167 $ git checkout HEAD~7 -b master # Tạo nhánh "master" mới 7 lần commit ngược từ trước.
169 Nhánh `master` bây giờ chỉ chứa Part I, và nhánh `part2` trở thành nhánh
170 chứa. Chúng ta đang ở nhánh sau; chúng ta đã tạo nhánh `master` mà không chuyển đến
171 nó, bởi vì chúng ta muốn tiếp tục làm việc trên `part2`. Điều này hơi bất thường. Cho đến lúc này,
172 Chúng ta chuyển đến các nhánh ngay sau khi chúng được tạo ra, như là trong:
174 $ git checkout HEAD~7 -b master # Tạo một nhánh và chuyển tới nó.
176 === Cải Tổ Lại Sự Pha Trộn ===
178 Có lẽ bạn thích làm việc trên mọi khía cạnh của một dự án trên cùng một nhánh. Bạn muốn giữ riêng các thay đổi mình đang làm cho riêng mình và muốn những người khác chỉ thấy được các lần commit của bạn sau khi đã được tổ chức lại. Hãy chuẩn bị một cặp nhánh:
180 $ git branch -b sanitized # Tạo một nhánh dùng cho việc dọn.
181 $ git checkout -b medley # Tạo và chuyển nhánh thành nơi làm việc.
183 Tiếp theo, làm việc gì đó: sửa lỗi, thêm các đặc tính kỹ thuật, thêm mã lệnh tạm thời, vân vân, commit thường xuyên. Sau đó:
185 $ git checkout sanitized # tạm dịch: đã được vệ sinh
186 $ git cherry-pick medley^^ # tạm dịch: hỗn độn; ^^: ông bà
188 áp dụng nhánh ông-bà của lần commit head của nhánh ``medley'' thành nhánh ``sanitized''. Với lệnh thích hợp là cherry-picks bạn có thể cấu trúc một nhánh mà nó chỉ chứa mã nguồn không thay đổi, và những lần commit có liên quan sẽ được nhóm lại với nhau.
190 === Quản Lý Các Nhánh ===
192 Liệt kê tất cả các nhánh bằng cách gõ:
196 Theo mặc định, bạn bắt đầu tại nhánh có tên ``master''. Một số người chủ trương rời bỏ
197 nhánh ``master'' mà không động chạm gì đến nó và tạo các nhánh mới dành cho các chỉnh sửa của riêng mình.
199 Các tùy chọn *-d* and *-m* cho phép bạn xóa hay di chuyển (đổi tên) các nhánh.
200 Xem thêm *git help branch*.
202 Nhánh ``master'' thông thường rất hữu dụng. Những người khác sẽ nghĩ rằng
203 kho chứa của bạn có nhánh mang tên này, và nhánh đó chứa phiên bản chính thức
204 của dự án của bạn. Mặc dù bạn có thể đổi tên hay xóa bỏ nhánh ``master'',
205 nhưng bạn không nên làm như thế mà hãy tôn trọng thỏa thuận ngầm này.
209 Một lát sau bạn có lẽ nhận thức được rằng mình cần có các nhánh tạm thời
210 vì các lý do như: mọi nhánh khác đơn thuần phục vụ cho
211 việc ghi lại trạng thái hiện tại do vậy bạn có thể nhảy trở lại các trạng thái cũ hơn để mà
212 sửa chữa các lỗi nghiêm trọng hay làm một cái gì đó.
214 Điều này cũng tương tự như việc chuyển kênh trên TV một cách tạm thời để thấy chương trình khác đang chiếu cái gì.
215 Nhưng thay vì chỉ cần nhấn vài cái nút, bạn phải tạo, ``checkout'',
216 trộn và xóa nhánh tạm đó. May mắn thay, Git có cách ngắn gọn tiện lợi
217 chẳng thua kém gì chiếc điều khiển từ xa của một chiếc TV:
221 Lệnh này ghi lại trạng thái hiện hành vào một vị trí tạm thời (một *stash*) và
222 phục hồi lại trạng thái trước đó. Thư mục bạn đang làm việc xuất hiện chính xác
223 như trước khi bạn chỉnh sửa, và bạn có thể sửa lỗi, pull về các thay đổi ngược dòng, và
224 cứ như thế. Khi bạn muốn qua trở lại trạng thái đã được tạm giấu đi đó, hãy gõ:
226 $ git stash apply # Bạn có thể sẽ phải giải quyết các xung đột có thể nảy sinh.
228 Bạn có thể có nhiều trạng thái được tạm giấu đi, và vận dụng chúng theo nhiều cách khác nhau. Xem
229 *git help stash* để biết thêm chi tiết. Bạn cũng có thể đoán được, Git duy trì các nhánh ở hậu trường để thực hiện việc này.
231 === Làm Theo Cách Của Mình ===
233 Bạn có thể sẽ cảm thấy việc sử dụng nhánh phiền hà quá. Cuối cùng, *clone* có lẽ là
234 lệnh nhanh nhất, và bạn có thể hoán chuyển giữa chúng với lệnh *cd* thay vì sử dụng
237 Ta thử xét đến các trình duyệt web. Tại sao việc hỗ trợ mở nhiều tab thì cũng tốt như mở trên nhiều cửa sổ khác nhau?
238 Bởi vì cả hai điều này thể hiện tính đa dạng của quan điểm, phong cách sống. Một số người sử dụng lại thích
239 chỉ giữ một cửa sổ trình duyệt được mở, và sử dụng các tab để hiển thị nhiều trang web một lúc. Những người khác
240 có lẽ lại khăng khăng cực đoan cho rằng: mở trên nhiều cửa sổ khác nhau và chẳng cần tab nữa.
241 Một nhóm khác lại thích cả hai cách trên.
243 Việc tạo nhánh thì cũng giống như tạo các tab cho thư mục làm việc của bạn, còn việc nhân bản thì lại giống như việc mở một cửa sổ duyệt mới. Những việc này nhanh chóng và nội bộ, thế thì sao lại không
244 thử nghiệm để tìm thấy cách nào thích hợp nhất cho mình? Git giúp bạn làm việc chính xác