Complete edit history, editing secrets.
[gitmagic/gitmagic.git] / vi / history.txt
blob9f052c1c68d2ac8d3ec59bcdeab158fc07cfed0b
1 == Bài Học về Lịch Sử ==
3 Một hệ quả tất yếu của đặc tính phân tán của Git là việc lịch sử có thể biên soạn lại một cách
4 dễ dàng. Nhưng nếu bạn xáo trộn quá khứ, hãy cẩn thận: chỉ biên soạn lại quá khứ trong lịch sử
5 chỉ khi bạn sở hữu nó một mình. Cũng giống như việc các quốc gia tranh cãi không kết thúc xem ai là người
6 tận tâm hành động nào là tàn ác, nếu một người khác có một bản sao mà lịch sử của nó lại khác với
7 cái của bạn, bạn sẽ gặp rắc rối ngay khi cần tương tác với họ.
9 Một số nhà phát triển phần mềm quả quyết rằng lịch sử không thể thay đổi, tất cả mọi thứ.
10 Một số khác lại cho rằng chỉnh sửa lại cấu trúc trước khi phát hành nó ra
11 đại chúng. Git chấp nhận cả hai quan điểm. Giống như việc nhân bản, tạo nhánh và hòa trộn,
12 viết lại lịch sử đơn giản chỉ là một quyền lực mà Git trao cho bạn. Bạn có thể làm thế
13 nếu muốn.
15 === Dừng Lại Sửa Chữa ===
17 Bạn vừa mới commit, nhưng lại ước mình đã gõ những dòng chú thích có nội dung khác phải không? Thế thì hãy chạy:
19  $ git commit --amend
21 để thay đổi chú thích cuối cùng. Bạn giật mình vì quên thêm các tệp tin vào? Chạy lệnh *git add* để
22 thêm nó vào, và sau đó lại chạy lệnh ở trên.
24 Bạn muốn thêm vài chỉnh sửa vào lần cuối mình đã commit ư? Thế thì cứ sửa chúng đi và sau đó chạy lệnh:
26  $ git commit --amend -a
28 === ... And Then Some ===
30 Hãy giả sử vấn đề trục trặc ở lần commit cách đây mười lần. Trong một buổi làm việc dài, bạn đã tạo ra hàng tá các lần commit. Nhưng bạn không hoàn toàn hài lòng với cách mà chúng được tổ chức, và một số lần commit cần được soạn lại phần mô tả. Thế thì hãy gõ:
32  $ git rebase -i HEAD~10
34 và 10 lần commit cuối sẽ xuất hiện trong $EDITOR yêu thích của bạn. Dưới đây là một đoạn trích ví dụ:
36     pick 5c6eb73 Added repo.or.cz link
37     pick a311a64 Reordered analogies in "Work How You Want"
38     pick 100834f Added push target to Makefile
40 Thế thì:
42 -Xóa bỏ các lần commit bằng cách xóa các dòng tương ứng.
43 -Đặt lại các lần commit bằng các đặt lại các dòng.
44 - Thay thế `pick` với:
45    * `edit` để đánh dấu lần commit đó là dành cho việc tu bổ (amend).
46    * `reword` để thay đổi phần chú giải.
47    * `squash` để hòa trộn với lần commit trước.
48    * `fixup` để hòa trộn với lần commit trước và bỏ qua việc ghi lại phần chú giải.
50 Ghi lại và thoát ra. Nếu bạn đánh dấu một lần commit dành cho việc 'edit', thế thì
51 chạy:
53  $ git commit --amend
55 Cách khác, chạy:
57  $ git rebase --continue
59 Do vậy cứ commit thoải mái và thường xuyên bởi vì bạn có thể dọn dẹp cho gọn gàng sau này bằng lệnh rebase.
61 === Các Thay Đổi Riêng Xếp Sau ===
63 Bạn đang làm việc trên một dự án đang hoạt động. Bạn đã tạo ra một số lần commit tại máy tính của mình, và
64 sau đó bạn đồng bộ hóa với cây chính thức bằng cách hòa trộn. Chu kỳ này tự lặp chính nó một số lần trước khi bạn thực sự push tới cây trên máy chủ trung tâm.
66 Nhưng hiện tại lịch sử bản sao Git trên máy tính của bạn là một mớ hỗn độn của những lần thay đổi trên máy tính riêng và máy chính thức. Bạn muốn thấy tất cả các thay đôi của riêng mình trong một đoạn liên tục không ngắt quãng, và sau tất cả các thay đổi từ văn phòng.
68 Đây chính là công việc dành cho lệnh *git rebase* đã được miêu tả ở trên. Trong nhiều trường hợp bạn có thể sử dụng
69 cờ *--onto* và tránh xa sự tương tác.
71 Xem thêm trong *git help rebase* để thấy được chi tiết các ví dụ dành cho lệnh đáng kinh ngạc này. Bạn có thể chia cắt các lần  commit. Bạn còn có thể xắp xếp lại các nhánh của một cấu trúc cây.
73 === Viết Lại Lịch Sử ===
75 Thỉnh thoảng, bạn muốn việc quản lý mã nguồn giống việc người ta sơn vẽ chân dung một
76 con người, tẩy xóa chúng từ lịch sử như theo ý của Stalinesque. Ví dụ,
77 giả sử chúng ta có ý định phát hành dự án, nhưng lại liên đới đến một tệp tin mà nóphải được giữ bí mật
78 vì lý do nào đó. Chẳng hạn như tôi đã quên khi ghi lại số thẻ tín dụng vào trong một tệp tin
79 văn bản và ngẫu nhiên nó được thêm vào trong dự án. Việc xóa tệp tin này là
80 chưa đủ, bởi vì ta có thể đọc nó từ lần commit cũ. Chúng ta phải gỡ bỏ
81 tệp tin này từ tất cả các lần đã commit:
83  $ git filter-branch --tree-filter 'rm top/secret/file' HEAD
85 Xem *git help filter-branch*, nội dung của nó sẽ thảo luận về ví dụ này và đưa ra một cách thức
86 nhanh hơn. Đại thể, lệnh *filter-branch* giúp bạn thay đổi cả một chương lớn của lịch sử chỉ
87 chỉ bằng một lệnh đơn.
89 Sau này, thư mục +.git/refs/original+ mô tả trạng thái của công việc trước khi thực hiện. Kiểm tra lệnh filter-branch đã làm những thứ bạn muốn chưa, sau đó xóa thư mục này đi nếu bạn muốn chạy lệnh filter-branch lần nữa.
91 Cuối cùng, thay thế bản sao của dự án của bạn bằng phiên bản bạn đã sửa lại nếu bạn muốn tương thích với chúng sau này.
93 === Tự Tạo Lịch Sử ===
95 [[makinghistory]]
96 Bạn muốn chuyển đổi dự án của mình sang sử dụng Git? Nếu nó được quản lý bởi một hệ thống nổi tiếng hơn, thế thì nếu may mắn sẽ có người nào đó đã viết sẵn một đoạn kịch bản để xuất toàn bộ lịch sử ra thành Git.
98 Nếu không, thì nên xem xét đến việc sử dụng lệnh *git fast-import*, lệnh này đọc văn bản đầu vào ở một định dạng
99 riêng để mà tạo ra một lịch sử cho Git từ ban đầu. Thông thường một script sử dụng
100 lệnh này là một nhóm lệnh tổ hợp với nhau và chỉ chạy một lần, di chuyển một dự án chỉ bằng
101 một lệnh đơn.
103 Dưới đây là một ví dụ, dán danh sách theo sau đâu vào một tệp tin tạm thời nào đó, chẳng hạn như là `/tmp/history`:
104 ----------------------------------
105 commit refs/heads/master
106 committer Alice <alice@example.com> Thu, 01 Jan 1970 00:00:00 +0000
107 data <<EOT
108 Initial commit.
111 M 100644 inline hello.c
112 data <<EOT
113 #include <stdio.h>
115 int main() {
116   printf("Hello, world!\n");
117   return 0;
122 commit refs/heads/master
123 committer Bob <bob@example.com> Tue, 14 Mar 2000 01:59:26 -0800
124 data <<EOT
125 Replace printf() with write().
128 M 100644 inline hello.c
129 data <<EOT
130 #include <unistd.h>
132 int main() {
133   write(1, "Hello, world!\n", 14);
134   return 0;
138 ----------------------------------
140 Thế thì tạo một kho Git từ thư mục chứa các tệp tin tạm thời này bằng cách gõ:
142  $ mkdir project; cd project; git init
143  $ git fast-import --date-format=rfc2822 < /tmp/history
145 Bạn có thể checkout phiên bản cuối của dự án với:
147  $ git checkout master .
149 Lệnh *git fast-export* chuyển đổi bất kỳ một kho chứa nào thành định dạng
150 phù hợp với lệnh *git fast-import*, và bạn có thể nghiên cứu nó để tạo riêng cho mình một chương trình xuất,
151 và cũng làm như thế để tạo thành kho chuyên chở ở định dạng con người có thể đọc được. Thực vậy,
152 những lệnh này có thể gửi một kho chứa ở dạng văn bản thông qua một kênh chỉ cho phép văn bản truyền đi.
154 === Vị Trí Nào Phát Sinh Lỗi? ===
156 Bạn vừa mới phát hiện ra một đặc tính không hoạt động trong chương trình mà bạn chắc chắn là nó đã hoạt động vài tháng trước. Tệ quá! Lỗi đến từ đâu nhỉ? Nếu như chỉ có mình bạn kiểm tra cũng như phát triển đặc tính này.
158 Lúc này thì đã quá muộn rồi. Tuy nhiên, chỉ cần bạn commit thường xuyên, Git
159 có thể xác định vị trí của trục trặc:
161  $ git bisect start
162  $ git bisect bad HEAD
163  $ git bisect good 1b6d
165 Git checks out một trạng thái nằm giữa chúng. Kiểm tra đặc tính kỹ thuật, và nếu nó vẫn hỏng:
167  $ git bisect bad
169 Nếu không thì thay "bad" bằng "good". Git sẽ chuyên chở bạn qua lại nửa bước giữa hai trạng
170 thái là phiên bản "tốt" và "xấu", thu hẹp khả năng lại. Sau khi lặp đi lặp lại một số lần,
171 việc tìm kiếm nhị phân này sẽ dẫn bạn đến lần commit mà nó làm nguyên nhân dẫn đễ hỏng hóc.
172 Một khi bạn đã hoàn tất việc điều tra, trở lại trạng thái nguyên bản
173 của bạn bằng cách gõ:
175  $ git bisect reset
177 Thay vì thử nghiệm mọi thay đổi một cách thủ công, hãy tự động hóa sự tìm kiếm này bằng cách chạy:
179  $ git bisect run my_script
181 Git sử dụng giá trị trả về của lệnh đã cho, thông thường là từ các đoạn script, để
182 quyết định là lệnh đã thực hiện tốt hay không: lệnh sẽ trả về giá trị 0
183 khi tốt, 125 khi sự thay đổi bị bỏ qua, và bất kỳ giá trị nào khác nằm giữa 1
184 và 127 nếu gặp lỗi. Một giá trị âm sẽ bãi bỏ lệnh bisect.
186 Bạn có thể làm nhiều hơn thế: trang trợ giúp giảng giải cho bạn làm thế nào để hiểu
187 được lệnh bisect làm việc như thế nào, xem xét hay xem lại nhật ký lệnh bisect,
188 và loại trừ các thay đổi ngớ ngẩn để tăng tốc độ tìm kiếm.
190 === Ai Đã Làm Nó Sai? ===
192 Giống như các hệ thống quản lý mã nguồn khác, Git cũng có lệnh blame:
194  $ git blame bug.c
196 lệnh này chú thích tất cả các dòng có trong tệp tin được chỉ ra cho thấy ai là người cuối cùng sửa nó, và là khi nào. Không giống các hệ thống quản lý mã nguồn khác, hành động này hoạt động không cần có mạng, việc đọc chỉ đơn thuần từ ổ đĩa của máy tính cá nhân.
198 === Kinh Nghiệm Riêng ===
200 Trong một hệ thống quản lý mã nguồn tập trung, thay đổi lịch sử là một việc làm
201 khó khăn, và chỉ làm được thế nếu đó là người quản trị. Việc nhân bản, tạo nhánh và
202 trộn không thể thiếu việc truyền thông qua mạng. Cũng như thế với các tác vụ cơ bản khác
203 như là duyệt lịch sử, hay là commit một thay đổi. Trong một số hệ thống khác, người dùng
204 yêu cầu có kết nối mạng chỉ để xem các thay đổi của họ hay mở một tệp tin
205 để biên tập.
207 Hệ thống tập trung không cho phép làm việc mà không có mạng, và đòi hỏi cơ sở hạ tầng mạng máy tính
208 đắt đỏ tốn kém, đặc biệt là khi số nhà phát triển phần mềm tăng lên. Điều quan trọng,
209 tất cả mọi tác vụ sẽ chậm hơn ở mức độ nào đó, thường thường
210 những người sử dụng sẽ lảng tránh việc sử dụng các lệnh cao cấp trừ phi nó thực sự cần thiết. Trừ những trường hợp
211 đặc biệt là các lệnh cơ bản. Khi những người dùng phải chạy
212 các lệnh chạy chậm, hiệu suất bị giảm bởi vì nó làm gián đoạn công việc của cả một dây truyền.
214 Tôi trực tiếp đã trải qua những hiện tượng đó. Git là hệ thống quản lý mã nguồn đầu tiên tôi sử dụng. 
215 Tôi nhanh chóng làm quen với nó, bị quyến rũ bởi những đặc tính kỹ thuật mà nó đã cung cấp.
216 Tôi đơn giản cho rằng các hệ thống khác thì cũng tương tự: việc chọn lựa một
217 hệ thống quản lý mã nguồn thì cũng chẳng khác việc chọn một trình biên soạn hay một
218 trình duyệt web.
220 Tôi sẽ sốc nếu như sau này bị bắt buộc sử dụng hệ thống quản lý mã nguồn tập trung. Một kết nối
221 Internet chậm chạp cũng chẳng phải là vấn đề lớn đối với Git, nhưng nó sẽ làm cho các
222 nhà phát triển phần mềm không thể chịu nổi khi nó cần sự tin cậy như ổ đĩa nội bộ. Thêm nữa,
223 tôi đã gặp một số mắc mớ với một số lệnh, mà chính nó
224 đã ngăn cản tôi làm việc một cách trôi chảy.
226 Khi tôi phải chạy những lệnh cần nhiều thời gian, việc làm ngắt quãng việc suy nghĩ
227 sẽ gây nên thiệt hại rất to lớn. Trong khi chờ cho việc truyền thông
228 với máy chủ hoàn tất, tôi sẽ phải làm một vài thứ gì đó khác để lấp chỗ trống, chẳng hạn như
229 lấy thư điện tử hay viết tài liệu. Sau một khoảng thời gian tôi quay trở lại nhiệm vụ
230 chính của mình, lệnh đã hoàn tất từ lâu rồi, và tôi phải lãng phí thêm nhiều thời gian nữa
231 để nhớ lại xem mình đang làm gì. Con người thường dở khi phải thay đổi mạch văn.
233 Ở đây còn có một hậu quả rất đáng quan tâm nữa: đoán trước được việc tắc nghẽn của mạng máy tính,
234 nhiều cá nhân riêng lẻ có thể chiếm dụng nhiều lưu lượng mạng hơn cần thiết trên các tác vụ
235 khác nhau để cố gắng giảm thiểu sự chậm trễ có thể xảy ra trong tương lai. Hậu quả cuối cùng là
236 sự quá tải quá mức, việc vô tình việc ủng hộ việc tiêu dùng cá nhân như thế làm đốt cháy nhiều lưu lượng mạng hơn
237 và sau đó nó làm cho việc tắc nghẽn càng lúc càng trở nên tồi tệ hơn.