Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Tìm hiểu cách sử dụng Git cơ bản

Tổng hợp bởi - tiennguyen98

Khái niệm

Git là tên gọi của một Hệ thống quản lý phiên bản phân tán (Distributed Version Control System – DVCS) là một trong những hệ thống quản lý phiên bản phân tán phổ biến nhất hiện nay. DVCS nghĩa là hệ thống giúp mỗi máy tính có thể lưu trữ nhiều phiên bản khác nhau của một mã nguồn được nhân bản (clone) từ một kho chứa mã nguồn (repository), mỗi thay đổi vào mã nguồn trên máy tính sẽ có thể ủy thác (commit) rồi đưa lên máy chủ nơi đặt kho chứa chính. Và một máy tính khác (nếu họ có quyền truy cập) cũng có thể clone lại mã nguồn từ kho chứa hoặc clone lại một tập hợp các thay đổi mới nhất trên máy tính kia. Trong Git, thư mục làm việc trên máy tính gọi là Working Tree. Đại loại là như vậy.

Mô hình hoạt động của DVCSMô hình hoạt động của DVCS Ngoài ra, có một cách hiểu khác về Git đơn giản hơn đó là nó sẽ giúp bạn lưu lại các phiên bản của những lần thay đổi vào mã nguồn và có thể dễ dàng khôi phục lại dễ dàng mà không cần copy lại mã nguồn rồi cất vào đâu đó. Và một người khác có thể xem các thay đổi của bạn ở từng phiên bản, họ cũng có thể đối chiếu các thay đổi của bạn rồi gộp phiên bản của bạn vào phiên bản của họ. Cuối cùng là tất cả có thể đưa các thay đổi vào mã nguồn của mình lên một kho chứa mã nguồn.

Cơ chế lưu trữ phiên bản của Git là nó sẽ tạo ra một “ảnh chụp” (snapshot) trên mỗi tập tin và thư mục sau khi commit, từ đó nó có thể cho phép bạn tái sử dụng lại một ảnh chụp nào đó mà bạn có thể hiểu đó là một phiên bản. Đây cũng chính là lợi thế của Git so với các DVCS khác khi nó không “lưu cứng” dữ liệu mà sẽ lưu với dạng snapshot.

Một vài khái niệm

git: là prefix của các lệnh được sử dụng dưới CLI

branch: được hiểu như là nhánh, thể hiện sự phân chia các version khi 2 version đó có sự sai khác nhất định và 2 version đều có sự khác nhau.

commit: là một điểm trên cây công việc (Work Tree ) hay gọi là cây phát triển công việc

clone: được gọi là nhân bản, hay thực hiện nhân bản. Sử dụng để clone các project, repository trên các hệ thống chạy trên cơ sở là git, ví dụ như: bitbucket, github, gitlab, cor(1 sản phẩm mã nguồn mở cho phép người dùng tự tạo git server cho riêng mình trên vps, server),... Việc clone này sẽ sao chép repository tại commit mình mong muốn, dùng để tiếp tục phát triển. Thao tác này sẽ tải toàn bộ mã nguồn, dữ liệu về máy tính của bạn.

folk: Folk là thao tác thực hiện sao chép repository của chủ sở hữu khác về git account của mình. sử dụng và đối xử như 1 repository do mình tạo ra.

repository: Kho quản lý dữ liệu, là nơi lưu trữ các dữ liệu, mã nguồn của project.

tag: sử dụng để đánh dấu một commit khi bạn có quá nhiều commit tới mức không thể kiểm soát được.

remote: sử dụng để điều khiển các nhánh từ một repository trên git server, đối xử với các nhánh trên remote tương tự như đối xử với các nhánh trên local

diff: So sánh sự sai khác giữa phiên bản hiện tại với phiên bản muốn so sánh, nó sẽ thể hiện các sự khác nhau

.gitignore: file mặc định của git sử dụng để loại bỏ (ignore) các thư mục, file mà mình không muốn push lên git server

Phân biệt merging và rebase

Link tham khảo

Những lệnh Git cơ bản

Tạo một repository mới

Để tạo 1 repository mới, bạn hãy mở cửa sổ lệnh và gõ dòng lệnh sau
git init

sao chép (clone) một repository

để clone 1 repository có sẵn ở trên máy cục bộ, bạn hãy sử dụng dòng lệnh sau:
git clone /đường-dẫn-đến/repository/
Nếu repository đó ở máy chủ khác thì bạn hãy gõ dòng lệnh sau:
git clone tênusername@địachỉmáychủ:/đường-dẫn-đến/repository

thêm (add) & commit

Bạn có thể đề xuất thay đổi (thêm nó vào chỉ mục Index) bằng cách
git add <tên-tập-tin>
git add *
Đây là bước đầu tiên trong quy trình git cơ bản. Để thật sự commit những thay đổi, bạn sử dụng
git commit -m "Ghi chú Commit"
Bây giờ thì tập tin đã được commit đến HEAD, nhưng chưa phải trên thư mục remote.

đẩy (push) các thay đổi

Thay đổi của bạn hiện đang nằm tại HEAD của bản sao cục bộ đang làm việc. Để gửi những thay đổi đó đến repository remote, bạn thực thi
git push origin master
Thay đổi master bằng bất cứ nhánh nào mà bạn muốn đầy những thay đổi đến.

Nếu bạn chưa clone một repository hiện có và muốn kết nối repository của bạn đến máy chủ remote, bạn phải thêm nó với
git remote add origin <máy-chủ>
Bây giờ bạn đã có thể đẩy các thay đổi của mình vào máy chủ đã chọn

nhánh

Các nhánh (branches) được dùng để phát triển tính năng tách riêng ra từ những nhánh khác. Nhánh master là nhánh "mặc định" khi bạn tạo một repository. Sử dụng các nhánh khác tri đang trong giai đoạn phát triển và merge trở lại nhánh master một khi đã hoàn tất.

tạo một nhánh mới và đặt tên là "feature_x": git branch -b feature_x
chuyển qua một nhánh git checkout feature_x
tạo một nhánh mới và đặt tên là "feature_x" và chuyển qua nhánh đó (từ master) bằng cách
git checkout -b feature_x
và xóa nhánh feature_x git branch -d feature_x
một nhánh không có giá trị với các nhánh khác trừ khi bạn đẩy nhánh đó đến remote repository
git push origin <nhánh>

cập nhật & trộn (update & merge)

để cập nhật repository cục bộ của bạn và commit mới nhất, thực thi
git pull
trong thự mục đang làm việc để lấy về (fetch)trộn (merge) các thay đổi ở remote.
để trộn một nhánh khác vào nhánh đang hoạt động (vd: master), sử dụng
git merge <nhánh>
trong cả hai trường hợp, git cố gắng trộn tự động (auto-merge) các thay đổi. Không may, điều này không phải lúc nào cũng làm được và thường dẫn đến xung đột. Trách nhiệm của bạn là trộn các xung đột đó thủ công bằng cách chỉnh sửa các tập tin được hiển thị bởi git. Sau khi thay đổi, bạn phải đánh dấu chúng là đã được trộn (merged) với lệnh
git add <tên-tập-tin>
trước khi trộn các thay đổi, bạn có thể xem trước chúng bằng các
git diff <nhánh_nguồn> <nhánh_mục_tiêu>

gắn nhãn (tagging)

người ta khuyên nên tạo nhãn (tags) khi phát hành phần mềm. đây là khái niệm được biết đến, đã từng có trên SVN. Bạn tạo tag mới tên là 1.0.0 bằng cách
git tag 1.0.0 1b2e1d63ff
chuỗi 1b2e1d63ff là 10 ký tự đầu tiên của mã commit (commit id) mà bạn muốn tham chiếu đến bằng nhãn của bạn. Bạn có thể lấy mã commit với lệnh
git log
bạn cũng có thể sử dụng ít ký tự hơn từ mã commit, nó chỉ cần phải là duy nhất.

thay thế các thay đổi cục bộ

Trong trường hợp bạn làm sai điều gì đó, bạn có thể thay thế các thay đổi cục bộ bằng lệnh
git checkout -- <tên-tập-tin>
lệnh này thay thế những thay đổi trong "tree" đang làm việc với nội dung mới nhất của HEAD. Các thay đổi đã được thêm vào chỉ mục, kể cả các tập tin mới, điều này sẽ được giữ lại.

Nếu bạn muốn hủy tất cả thay đổi và commit cục bộ, lấy về (fetch) lịch sử gần đây nhất từ máy chủ và trỏ nhánh master cục bộ vào nó như sau
git fetch origin
git reset --hard origin/master

Lưu đăng nhập tài khoản Git

Chạy lệnh: git config credential.helper store

Sau đó chạy git push ** ** rồi nhập thông tin đăng nhập 1 lần. Từ sau không cần nữa.

So Sánh "git fetch" và "git pull"

Như vậy lưu ý rằng câu lệnh git pull $remote_origin $branch_name sẽ tải về (hay fetch) dữ liệu từ một branch duy nhất $branch_name từ remote server và sau đó merge các thay đổi từ remote này vào repository dưới local.

Ngược lại git fetch $remote_origin sẽ tải về (fetch) dữ liệu của toàn bộ các branch trên URL quy định bởi $remote_origin nhưng không thực hiện việc merge các thay đổi này vào local.

Git diff

  • git diff View difference between Stage and Working Directory
  • git diff --staged View difference between HEAD and Stage
  • git diff HEAD View difference between HEAD and Working Directory

Git reset

  • reset --soft : History changed, HEAD changed, Working directory is not changed.
  • reset --mixed : History changed, HEAD changed, Working directory changed with unstaged data.
  • reset --hard : History changed, HEAD changed, Working directory is changed with lost data.

1.1 Quy trình làm việc Git

Những bước chính dưới đây:

  • Cho một dự án mới, khởi tạo một repository git trong danh mục dự án. Đối với các tính năng / thay đổi tiếp theo, bước này sẽ bị bỏ qua.

    cd <project directory>
    git init
  • Checkout một nhánh tính năng hoặc nhánh để sửa lỗi.

    git checkout -b <branchname>
  • Tạo sự thay đổi.

    git add
    git commit -a

    Tại sao:

    git commit -a sẽ bắt đầu một editor mà nó cho phép bạn tách chủ đề khỏi thân. Đọc thêm về nó tại mục 1.3.

  • Đồng bộ với điều khiển để có sự thay đổi mà bạn đã bỏ lỡ

    git checkout develop
    git pull

    Tại sao:

    Điều này sẽ cung cấp cho bạn một cơ hội để đối phó với các xung đột trên máy của bạn trong khi rebase (sau này) hơn là tạo một pull request có chứa xung đột.

  • Cập nhật nhánh tính năng với thay đổi cuối cùng từ develop bằng việc rebase.

    git checkout <branchname>
    git rebase -i --autosquash develop

    Tại sao:

    Bạn có thể dùng --autosquash để squash tất cả commit của bạn đến một commit riêng. Không ai muốn nhiều commit cho một tính năng trong nhánh develop. đọc thêm...

*Nếu bạn không có xung đột, bỏ qua bước này. Nếu bạn có, giải quyết chúng và tiếp tục rebase. sh git add <file1> <file2> ... git rebase --continue

  • Push nhánh của bạn. Rebase sẽ thay đổi lịch sử, vật bạn sẽ phải dùng -f để bắt buộc những thay đổi trong nhánh điều khiển. Nếu một ái đó khác đang làm việc trên nhánh của bạn, sử dụng --force-with-lease để giảm lỗi.

    git push -f

    Tai sao:

    Khi bạn rebase, bạn đang thay đổi lịch sử trong nhánh tính năng của bạn. Giống như một kết quả, Git sẽ từ chối bình thường git push. Tahy vào đó bạn sẽ cần sử dụng -f hoặc --force. đọc thêm tại...

  • Tạo một pull request

  • Pull request sẽ được chấp nhận, merge và đóng bởi người review.

  • Xóa nhánh tính năng trên local của bạn nếu bạn đã hoàn thành.

    git branch -d <branchname>

    to remove all branches which are no longer on remote Để xóa tất cả nhánh mà nó đã lâu không điều khiển

    git fetch -p && for branch in `git branch -vv --no-color | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done

1.2 Một vài quy tắc của Git

Có một bộ các quy tắc cần được ghi nhơ:

  • Thực hiện công việc trong một nhánh tính năng

    Tại sao:

    Bởi vì cách với tất cả công việc được hoàn thành trong sự cô lập trên một nhánh chuyên dụng hơn là nhánh chính. Nó cho phép bạn submit nhiều pull request không có nhầm lẫn. Bạn có thể lặp lại mà không gây sai xót cho nhánh chính với code không ổn định, code chưa hoàn thành. đọc thêm tại...

  • Chia nhánh từ develop

    Tại sao:

    Cách này, bạn có thể chắc chắn rằng code trong master sẽ gần như luôn luôn xây dựng mà không có vấn đề, và có thể sử dụng trực tiếp cho việc phát hành ( nó có thể quá mức cho một vài dự án).

  • Đừng bao giờ push lên nhánh develop hoặc master. Tạo một pull request.

    Tại sao:

    Nó thông báo cho các thành viên trong nhóm rằng họ đã hoàn thành một tính năng. Nó cũng cho phép dễ dàng đánh giá ngang hàng của code và có riêng diễn đàn cho việc thảo luận về tính năng đã đề xuất.

*Cập nhật nhánh develop ở trên local của bạn và thực hiện rebase trước khi push tính năng của bạn và tạo một pull request.

_Tại sao:_
> Việc rebase sẽ merge trong nhánh được yêu cầu (`master` hoặc` develop`) và áp dụng các commit mà bạn đã thực hiện ở local trên đầu lịch sử mà không tạo ra một merge commit (giả sử rằng không có xung đột). Kết quả là một lịch sử đẹp và sạch sẽ. [read more ...](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)
  • Giải quyết xung đột trong khi rebase và trước khi thực hiện pull pequest.

  • Xóa local và nhánh tính năng sau khi merge.

    Tại sao:

    Nó sẽ làm xáo trộng danh sách các nhánh của bạn với nhánh đã bỏ. Nó đảm bảo bạn chỉ merge khi các nhánh vào trong (master hoặc develop) một lần. Các nhánh tính năng nên chỉ tồn tại trong khi công việc vẫn trong quá trình.

  • Trước khi thực hiện pull request, hãy đảm bảo nhánh tính năng của bạn được xây dựng thành công và vượt qua tất cả các test (bao gồm kiểm tra phong cách code).

    Tại sao:

    Bạn sắp thêm code của bạn vào một nhánh ổn định. Nếu nhánh tính tăng test sai, có một cơ hội cao rằng nhánh mà bạn xây dựng cũng sẽ sai. Thêm nữa, bạn cần áp dụng phong cách code trước khi tạo pull request. Nó hỗ trợ khả năng đọc và giảm khả năng sửa các định dạng được trộn lẫn với các thay đổi thực tế.

  • Dùng file this .gitignore.

    Tại sao:

    Nó đã có danh sách các tệp hệ thống không được gửi cùng với mã của bạn vào một repository. Ngoài ra, nó không bao gồm cài đặt thư mục và tệp cho hầu hết các editor được sử dụng, cũng như các thư mục chung thuộc phổ biến nhất

  • Bảo vệ nhánh developmaster

    Tại sao:

    Nó bảo vệ các nhánh sản phẩm đã sẵn sàng của bạn khỏi những thay đổi bất ngờ và không thể đảo ngược. đọc thêm tại... Github, Bitbucket and GitLab

1.3 Viết lời nhắn khi commit

Việc có một dòng hướng dẫn cho việc commit và việc gắn bó với nó làm cho việc làm việc với Git và công tác viên cùng với rất nhiều thứ khác dễ dàng hơn. Đây là một vài quy tắc. (nguồn):

Tách riêng chủ đề khỏi phần thân với một dòng giữa chúng

_Tại sao:_
> Git đủ thông minh để phân biệt dòng đầu tiên của lời nhắn commit của bạn dưới dạng tóm tắt. Trong thực tế, nếu bạn thử git shortlog, thay vì git log, bạn sẽ thấy một danh sách dài các lời nhắn commit, bao gồm id của commit, và bản tóm tắt duy nhất.
  • Giới hạn dòng chủ đề ở 50 chữ và gói gọn phần thân trong 72 chữ.

    Tại sao

    Các commit nên được làm tốt và tập trung nhất có thể, nó không phải là nơi để được verbose. đọc thêm...

  • Viết hoa dòng chủ đề.

  • Không kết thúc dòng chủ đề với một khoảng.

  • Dùng Tình trạng gấp trong dòng chủ đề.

    Tại sao:

    Thay vì viết tin nhắn cho biết những gì người commit đã làm. Tốt nhất nên xem xét các thông báo này như là hướng dẫn cho những gì sẽ được thực hiện sau khi commit được áp dụng trên repository. đọc thêm...

  • Dùng phần thân để giải thích cái gìtại sao giống như phản đối tại sao.

Gitignore:

Gitignore là file có tên là .gitignore, nhiệm vụ của nó là liệt kê những file mà mình không mong muốn cho vào cho lên Git. Ví dụ như trong một dự án mỗi người có thể sẽ dùng một IDE khác nhau. Khi dó IDE có thể sinh ra những file rác vào trong dự án, gây rối mắt hoặc conflict cho người khác. Vì vậy phải dùng .gitignore.

Các cú pháp cơ bản trong .gitignore

  • Sử dụng # để comment.
  • Điền tên file cần loại bỏ: tenfile.php
  • Loại bỏ thư mục: example_folder/
  • Khi ignore thư mục nên có dấu / ở sau tên thư mục để nhận biết đó là thư mục.
  • Dấu ! phía trước có ý nghĩa phủ định: !abc/example.exe
  • Xóa file cùng đuôi *.xml
  • Trường hợp khác của 1 * nếu bạn chỉ rõ đường dẫn ví dụ: config/*.xml thì nó chỉ có hiệu lực cho các file config/abc.xml.
  • Dùng **/folder nó sẽ có hiệu lực cho tất cả folder ở khắp nơi trong dự án.
  • Hay sử dụng kiểu folder/** để có hiệu lực cho tất cả các file bên trong thư mục.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.