Git Tutorial P.2
Tiếp nối phần trước, mình đã hướng dẫn cơ bản cho các bạn cách sử dụng Git cơ bản. Hôm nay, trong bài này mình sẽ tập trung hướng dẫn cách sử dụng Git nâng cao và thực tế hơn một chút là cách sử dụng Git trong công việc. Để xem lại phần 1 nhấn vào đây : Phần 1 Trong công việc, nếu như bạn ...
Tiếp nối phần trước, mình đã hướng dẫn cơ bản cho các bạn cách sử dụng Git cơ bản. Hôm nay, trong bài này mình sẽ tập trung hướng dẫn cách sử dụng Git nâng cao và thực tế hơn một chút là cách sử dụng Git trong công việc. Để xem lại phần 1 nhấn vào đây : Phần 1
Trong công việc, nếu như bạn không phải là leader hay người quản lý dự án (người được quyền quản lý mã nguồn của dự án) thì bạn sẽ không cần phải khởi tạo mã nguồn cho dự án. Thông thường, người quản lý dự án sẽ cho bạn một link github mã nguồn của dự án để bạn làm việc.
1. Clone, Fork
Với các dự án mã đã được khởi tạo mã nguồn, bạn cần phải lấy mã nguồn trên github về máy của mình để bắt đầu làm việc. ![alt](http://www.jonathanpberger.com/code_management/images/git-clone.png =400)
// git clone [link github] [project name] > git clone https://github.com/MichalPlachyFramgia/demoGitTut demoGitTut // git checkout -b [branch] > git checkout -b develop // git pull [remote] [branch] > git pull origin develop
Ví dụ ở đây mình tạo 1 project demo là demoGittut. Sau khi clone về thì toàn bộ các file của project sẽ có ở trên máy của bạn. Mặc định nhánh ban đầu khi bạn đang ở sẽ là master, bạn nên checkout tạo nhánh mới để bắt đầu có thể viết mã của mình. Ở đây mình checkout ra nhánh mới có tên là develop và lấy mã từ nhánh develop ở trên github về.
Ngoài ra đối với các dự án phát triển thêm các feature mới (lớn) mà không muốn làm thay đổi code cũ trên github (core), bạn phải fork dự án về và phát triển thêm thì bạn có thể làm như sau:
- Nhấn Fork trên trang github của project bạn muốn fork.
- lúc này mã nguồn dự án sẽ được copy về trang github là project của bạn.
- bạn có thể cập nhật mã nguồn của mình vào project core nếu được cho phép.
- bạn có thể cập nhập các thay đổi mới ở core về project của mình.
- Git clone link project trên trang github của bạn (tương tự như ở trên).
- Bắt đầu bắt tay làm công việc của mình (code, review, test,...).
2. Branch
Sau khi lấy được mã nguồn về thì ta sẽ được bắt đầu tạo các nhánh để viết mã. Về quản lý mã nguồn thì ứng với mỗi dự án, mỗi công ty sẽ có cách quản lý mã khác nhau nhưng thường mã nguồn sẽ được chia làm 2 đến 3 nhánh chính. Kiểu như thế này
1 nhánh cho production (master):- Nhánh này đảm nhiệm lưu trữ code thực thi trên production gồm các config cài đặt phù hợp để có thể chạy ổn định trên production.
- Nhánh này đảm nhiện lưu trữ code trên develop gồm các cài đặt phù hợp để thực hiện việc test trên develop. Chỉ khi việc test trên develop thực sự ổn định và hoàn thiện thì mới được đưa sản phẩm lên production
- Nhánh này đảm nhiệm nhiệm vụ đưa từng phần các nhánh nhỏ gộp vào với nhau để thực hiện test các phần nhỏ vừa mới làm xong.
Ngoài ra, có thể có các nhánh phụ phụ thuộc vào dự án và công ty bạn đang làm. Nếu có thêm các nhánh phụ thì đó là các nhánh thể hiện các chức năng lớn của dự án. Trong các nhánh phụ sẽ có thể có các nhánh con nhỏ hơn nữa thể hiện các phần nhỏ hơn của chức năng đó. Nếu một dự án được chia làm nhiều phần và các phần được do các công ty hay các bộ phận khác nhau làm thì khi đó chắc chắn cần phải có các nhánh phụ này. Các nhánh phụ lớn này sẽ được giữ đến khi bạn kết thúc dự án hoặc khi chức năng đó không còn cần được dùng đến nữa. Với các dự án rất lớn thì việc giữ lại các nhánh phụ này là cần thiết để dễ dàng cho việc debug và sửa chữa mã sau này.
Các nhánh mới được tạo ra phải thể hiện được rõ chức năng cụ thể của nó. Việc đặt tên nhánh rất quan trọng vì nó sẽ giúp người hiểu được nhánh nào làm việc gì, giúp việc maintain hoặc phát triển thêm sau này dễ dàng hơn. Các nhánh được tạo nên được phân chia các công việc rạch ròi và càng ít hoặc không liên quan đến các nhánh khác càng tốt.
Việc test sẽ được thực hiện ở các nhánh con nhỏ nhất rồi lên dần đến các nhánh lớn hơn.
Một vài lệnh bạn có thể sử dụng với branch:
// Tạo nhánh mới > git branch -b [branch]
// Xóa nhánh > git branch -D [branch]
// check sang nhánh > git checkout [branch]
// đổi tên hoặc di chuyển nhánh > git branch -m [oldbranch] [newbranch]
// xem tất cả các nhánh hiện có git branch --all
3. Commit
Đối với một số công ty hay dự án thì đôi khi không yêu cầu quy chuẩn cho các commit (thường thì là các dự án nhỏ). Tuy nhiên, việc commit nhằm đảm bảo và phân chia các mã nguồn ứng với các chức năng bạn code một cách rạch ròi chi tiết nhất. Bạn nên chia công việc của mình ra nhiều commit (không nên chia nhỏ quá) mà đảm bảo mỗi commit của bạn có một chức năng hoàn thiện hoặc một tác vụ cụ thể nào đó. Việc viết tên commit sao cho chính xác với nội dung commit cũng rất quan trọng. Vì chúng có thể được dùng cho việc tìm và sửa lỗi sau này. Khi viết code thì việc bị comment do các đoạn code viết chưa được tối ưu hay gặp bug phải sửa chữa lại code thì việc phải commit đi lại nhiều trên một nhánh chắc chắn bạn sẽ gặp phải. Vậy khi nào thì nên để nhiều commit và khi nào thì nên gộp các commit lại làm một ?
Khi các bạn code xong 1 chức năng hoặc 1 tính năng mới và đẩy lên thì bạn sẽ được những người làm việc có kinh nghiệm hơn review code hoặc nếu không có thì chắc chắn cũng sẽ có công đoạn các tester viết các unittest, test case và tìm lỗi trên mã nguồn bạn viết ra. Khi trong quá trình được review hay test thì bạn nên thêm mới các commit ứng với các phần bạn sửa để người review và test dễ dàng theo dõi quá trình bạn sửa và nhận biết bạn đã sửa đúng chưa hay là sai. Tuy nhiên, khi code đã hoàn thiện và sửa xong hết thì trước khi mã của bạn được merge vào nhánh trên, bạn nên gộp các commit đó lại vì khi đó không ai quan tâm bạn đã làm và sửa được những gì ở nhánh của mình nữa. Việc gộp commit lại sẽ giúp người quản lý theo dõi mã nguồn của dự án được tốt hơn. Nếu nhánh của bạn là một nhánh con nhỏ thì sau này chắc chắn nó sẽ bị xóa đi. Các commit chỉnh sửa nhỏ không cần thiết phải được lưu trữ lại nên tốt nhất là nên gộp các commit lại cho tiện. Để gộp các commit bạn có thể sử dụng lệnh sau:
Việc chỉnh sửa các commit như này rất là nguy hiểm nên cần phải chú ý khi sử dụng.
// gộp vào với commit trước > git commit --am // gộp N commit >git rebase -i HEAD~{N} //thêm lại các file đã sửa đổi > git add [filepath] [filepath] // commit lại message mới > git commit -m 'message'
4. DIFF
Sau khi viết mã xong bạn cần phải xem lại các sửa đổi của mình. Thường thì có khá nhiều công cụ hỗ trợ nhưng nếu đối với trường hợp mà không thể sử dụng các công cụ này thì mình xin hướng dẫn qua về command để xem lại các thay đổi mà bạn đã tạo. ![alt](http://image.beekka.com/blog/201208/bg2012082901.png =500)
//xem các thay đổi đối với các file chưa được thêm vào working tree (chưa git add) > git diff //xem thay đổi giữa nhánh hiện tại và nhánh chọn > git diff [branch] //xem thay đổi giữa 2 nhánh > git diff [branch1] [branch2] //xem thay đổi giữa các commit > git diff [commit1] [commit2] //xem thay đổi của file chỉ định > git diff [file]
5.STASH
Để lưu tạm thời những thay đổi đang làm mà chưa commit được thì git có một chức năng rất hay đó là stash. Đây là một dạng bộ nhớ tạm dùng để lưu các thay đổi đang làm mà chưa commit, sau đó phục hồi code về nguyên trạng ban đầu trước khi có những thay đổi đó. Áp dụng khi bạn đang code dở tay một chức năng gì đó, chưa xong mà cần phải pull code về. Khi đó bạn chỉ cần gõ lệnh:
//lưu tất cả các thay đổi vào stash > git stash //Để xem danh sách các stash đã lưu: > git stash list //Lấy thay đổi từ stash mà không xóa stash đó đi > git stash apply // Lấy các thay đổi ra và xóa stash đó đi > git stash pop //lấy thay đổi từ 1 stash bất kỳ > git stash apply [stash] //Xóa bỏ toàn bộ stash > git stash clear
6. REBASE & REVERT
Việc sử dụng chung một mã nguồn thì việc mã nguồn không đồng nhất là điều khó tránh khỏi. Chính vì vậy nên mình khuyên các bạn là sau khi làm xong thì hãy thực hiện update lấy mã nguồn mới nhất về để kiểm tra xem có bị xung đột không. Nếu có thì bạn phải sửa lại (fix conflict) rồi mới thực hiện đẩy mã nguồn mới của bạn lên (Đằng nào cũng phải sửa thì sửa sớm trước khi đẩy lên sẽ tốt hơn). Khi bạn lấy mã nguồn trên một nhánh lớn (nhánh cha) thì bạn phải thực hiện cập nhật trên nhánh con bằng cách sử dụng git rebase
// Gộp code từ branch trên remote về branch hiện tại > git rebase [branch] //Nếu bị conflict thì phải sửa các file bị conflict và tiến hành add lại file git add [file] //Tiến hành tiếp tục rebase git rebase --continue //hoặc bỏ qua conflict và rebase git rebase --skip //hoặc đảo ngược quá trình không rebase nữa git rebase --abort
Ngoài ra nếu muốn cập nhập code từ nhánh ông mà không cập nhập từ nhánh cha thì ta có thể dùng command sau:
> git rebase --onto [grandBranch] next [childBranch]
Phần rebase này khá là phức tạp nên nếu muốn tìm hiểu thêm các bạn có thể xem thêm ở đây.
Nếu như rebase là gộp lại các thay đổi thì revert là quá trình đảo ngược lại các thay đổi. Sau đây là một vài command bạn có thể dùng khi cần.
//hủy các thay đổi và tạo commit tương ứng > git revert //hủy các thay đổi và không tạo commit > git revert -n //tiếp tục revert > git revert --continue //thoát không thực hiện revert > git revert --quit //đảo ngược về trước khi revert > git revert --abort
Command nguy hiểm
Sau đây mình xin giới thiệu một vài command nguy hiểm mà có thể bạn cần biết. Đây là các command mà khi chạy sẽ gây tác động lớn đến công việc hiện tại của bạn. Bạn cần phải hiểu rõ việc mình đang làm thì mới dùng đến các command này nhé
// hủy bỏ toàn bộ các thay đổi chưa được add vào working tree > git clean
// reset và hủy bỏ toàn bộ các thay đổi. > git reset --hard
Cần phải chú ý khi thực hiện command này vì nó sẽ xóa hết các thay đổi về mã nguồn của bạn và đưa về trạng thái chưa sửa đổi
Các vấn đề có thể gặp phải khi dùng Git và cách giải quyết
- Vấn đề non-fast-forward errors
Đôi khi, bạn không thể cập nhật thay đổi lên remote mà không bị mất commit cũ. Nếu như có một người khác cũng đẩy mã mới lên và trùng với branch bạn đang đẩy lên thì Git sẽ không cho phép bạn push các thay đổi lên
> git push origin master To https://github.com/USERNAME/REPOSITORY.git ! [rejected] master -> master (non-fast-forward) error: failed to push some refs to 'https://github.com/USERNAME/REPOSITORY.git' To prevent you from losing history, non-fast-forward updates were rejected Merge the remote changes (e.g. 'git pull') before pushing again. See the 'Note about fast-forwards' section of 'git push --help' for details.
Bạn có thể sửa bằng cách fetch và merge các thay đổi ở nhánh đã có trên remote về nhánh của bạn.
> git fetch origin # Fetches updates made to an online repository > git merge origin YOUR_BRANCH_NAME # Merges updates made online with your local work
Hoặc bạn có thể chỉ cần sử dụng command git pull để thực hiện giống như trên
> git pull origin YOUR_BRANCH_NAME
- Các giới hạn của git ?
Các file text lớn hơn 1MB luôn được đưa lên dạng plant-text và không được chuyển sang HTML
Các file text lớn hơn 5MB sẽ chỉ được hiện thị url chứ không hiển thị nội dung
Giới hạn của diff Không file diff nào được chứa quá 1500 dòng thay đổi hoặc 100kb dữ liệu. Tất cả các file sẽ không được quá 10000 dòng code hoặc 1MB dữ liệu
Tổng cộng tối đa số file được thay đổi để diff ra là 300
nếu vượt quá giới hạn đó thì những phần thừa ra sẽ vấn được tính nhưng không được hiển thị lên.
Số commit tối đa được hiển thị lên là 500 commit
- **Cách lấy về tất cả các nhánh trên remote **
Sử dụng command sau để lấy. Các nhánh này thực chất đã được lấy về sau khi bạn clone nhưng bị ẩn.
> git branch -a
- Làm sao để phục hồi lại file đã bị xóa
Đầu tiên ta phải tìm thấy commit cuối cùng mà file đó còn tồn tại. Sau đó ta chạy lệnh:
> git rev-list -n 1 HEAD -- [filename]
Rồi sau đó checkout file ra để hồi phục:
> git checkout [commit] -- [filename]
- Đưa 1 file về trạng thái của commit trước đó
Đôi khi, sau một vài commit bạn nhận ra những chỉnh sửa mới trên 1 file của bạn bị sai. Bạn có thể dùng command sau để đưa file về với trạng thái trước đó.
> git checkout [commit] [filename]
- Tôi đang có một nhánh local và muốn nhánh này chỉ đến 1 nhánh trên remote thì làm thế nào ?
Giả sử nhánh local của bạn là local và nhánh trên remote là remote thì nếu như bạn đang ở trên nhánh local thì bạn có thể dùng command sau:
> git branch -u remote/local
- Tôi quên thêm .gitignore nên đã up cả các file .exe,.. lên github thì phải làm thế nào ?
Bạn đầu tiên là phải tạo file gitignore rồi sau đó chạy command sau đê remove các file cần thiết ra khỏi remote. Command này là remove tất cả các file có đuôi .exe
> git rm --cached /*.exe
Many thanks.