Skip to content

Lệnh GIT thường dùng (Basic GIT command)

Những lệnh thường dùng để thao tác với GIT

# -- Xem trạng thái hiện tại của GIT, các file đã thay đổi so với local repository
git status
# -- Add file to local repository
git add <filename> | *
# -- Commit file to local repository
git commit -m "Commit message" <==> git commit -a
# -- Push the branch to your remote repository, so others can use it
git push | origin <branchname>
# -- Fetch and merge changes on the remote server to your working directory
git pull
# -- To merge a different branch into your active branch (local repository)
git merge <branchname>
# -- show current branch (with -a show all)
git branch
# -- Switched to a new branch "iss53"
git checkout -b iss53 
# -- Switched and create a new branch [branch_name] from origin/[branch_name]
git checkout -b [branch_name] origin/[branch_name]
# -- Create a new branch from a TAG NAME
git checkout -b <branch_name> <form_TAG_Name>
# -- Discard, reset file or multi files in folder
git checkout <filename> | *

Tạo và xử lý một Branch từ TAG NAME

Thường dùng để phát triển thêm chức năng khác từ một bộ source có sẵn đã có release version và đánh TAG NAME

# -- 1. Tạo mới branch từ TAG name 
git checkout -b <branch_name> <tag_name>
# -- Ex: git checkout -b NewBranchName v1.0
# -- 2. Make changes to pom / release versions
# -- 3. Stage changes
# -- 4. Add và Commit sự thay đổi lên local repository 
git commit -m "Update pom versions for Hotfix branch"
# -- 5. Finally push your newly created branch to remote repository.
git push -u origin <NewBranchName>

CLONE một branch từ Remote Repository Link

Dùng để chọn phát triển tiếp từ một bộ source với branch bất kì. Sau khi phát triển xong ta có thể đưa nó lên làm Remote Repository riêng của mình.

# -- Tao git clone cho thu vien DbCoreKit
# -- Use the --single-branch switch (available as of Git 1.7.10). The syntax is:
git clone -b <tag_name> --single-branch <repo_url> [<dest_dir>]

# -- For example:
git clone -b 'v1.9.5' --single-branch https://github.com/git/git.git git-1.9.5  
git clone -b 'done_v1.1.1' --single-branch http://dylan_bui@sc.propzy.vn/root/propzy-swift-library.git DbCoreKit-Rel.1.1.1

Push source code lên Empty Remote Repository (Gitlab, Github)

Thường dùng đưa first project, project framework lên remote repository.

# -- 1. Thư mục dự án chưa có cấu hình GIT. Go to current folder
git init
# -- 2. Add, Commit source code vào local repository
git add .
git commit -m "First commit"
# -- 3. Add Remote Repository link
git remote add origin <Link Gitlab/Github Repository>
# -- 4. Set upstream branch mapping local branch
git branch --set-upstream-to=origin/master master
# -- 5. Pull source code from remote repository
git pull --allow-unrelated-histories
# -- For error : fatal: refusing to merge unrelated histories
# -- git pull origin master --allow-unrelated-histories
git pull
git commit -m 'commit'
# -- 6. Push source code to remote repository
git push

Kỹ thuật UNDO một số command trên GIT

Dùng 'git status' xem trạng thái local branch

Chúng ta dùng câu lệnh git status để xem trạng thái hiện tại của local branch và nó sẽ gợi ý cách xử lý tiếp theo.

git restore : undo file đã thay đổi

Khi ta thay đổi file, chạy lệnh này nó sẽ bỏ qua sự thay đổi. Có thể dùng git status để coi gợi ý cách xử lý.

git status
# -----
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified:   README.md

git restore --staged : undo file đã được add

Khi ta đã add file, chạy lệnh này nó sẽ trở lại như chưa add, sự thay đổi của file vẫn còn. Có thể dùng git status để coi gợi ý cách xử lý.

git status
# -----
Your branch is up to date with 'origin/main'.
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    modified:   README.md

Undo khi đã commit code thành công

# -- Xem trạng thái
git status
# -----
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean
# -- Dùng lệnh git log để xem ds commit, last local commit sẽ nằm trên đầu có Hash number và (HEAD -> main) at the end.
git log
# ----
commit 699fbe6ae9b74e18f9b8eedef4f51cfc8d56e6e7 (HEAD -> feature/dylanbui/auto-test)
Author: Duc Bui <duc@propzy.com>
Date:   Sun Apr 28 16:51:12 2024 +0700
    thu undo coi
# -- Chạy lệnh, nó sẽ remote last local commit
git reset --soft HEAD~
# -- remove the last two commits from top
# -- git reset --soft HEAD~2
# -- Kiểm tra lại bằng git log sẽ thấy không còn last commit
git log
# -- Kiểm tra bằng git status sẽ thấy trở lại trạng thái đã add file
git status
# ----
Your branch is up to date with 'origin/main'.
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    modified:   README.md

Undo khi đã PUSH code lên Remote repository

# -- Kiểm tra bằng lệnh git status
git status
# -----
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
# -- Trạng thái source code đã push tất cả lên remote repository
# -- Kiểm tra log online trên remote repository
git log --oneline
# -- Chúng ta sẽ thấy latest commit với 1 commit Hash number và (HEAD -> <branch_other_push_to>)
# -----
6b84b4a (HEAD -> feature/dylanbui/auto-test, origin/feature/dylanbui/auto-test) revert thang push nay
1323f56 auto deploy
380e52a auto-test
10212a3 (origin/develop, develop) Merge branch 'feature/dylanbui/auto-deploy' into 'develop'
# -- undo push với câu lệnh
git revert <hash_number> --no-edit
# -- Ví dụ o đây hash_number = 6b84b4a
# -- git revert 6b84b4a --no-edit
# -- Xem lại log sẽ thấy 'revert' sẽ được thêm vào như là latest commit
2ad8bfd (HEAD -> feature/dylanbui/auto-test) Revert "revert thang push nay"
6b84b4a (origin/feature/dylanbui/auto-test) revert thang push nay
1323f56 auto deploy
380e52a auto-test
10212a3 (origin/develop, develop) Merge branch 'feature/dylanbui/auto-deploy' into 'develop'
# -- Xem lại bằng lệnh git status, trạng thái đã được chuyển lại trước khi push
git status
# -----
On branch feature/dylanbui/auto-test
Your branch is ahead of 'origin/feature/dylanbui/auto-test' by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working tree clean

Tìm hiểu các câu lệnh dùng UNDO Git

GIT LOG và GIT LOG --ONELINE

# -- Xem log tại local repository
git log
# -- Xem log tại remote repository
git log --oneline

GIT RESET

Git reset được sử dụng để di chuyển HEAD (con trỏ chỉ đến commit hiện tại) trỏ đến một commit cụ thể. Sau đó, xóa đi các commit có thời gian sau nó.

git reset <hash_commit>
# -- <hash_commit> được hiển thị trong git log
# -- Thường sử dụng
git reset  --hard|soft HEAD     -> Di chuyển con trỏ đến commit hiện tại.
git reset  --hard|soft HEAD^    -> Quay về trước 1 commit so với HEAD.
git reset  --hard|soft HEAD~1   -> Quay về trước 1 commit so với HEAD.
git reset  --hard|soft HEAD~2   -> Quay về trước 2 commit so với HEAD.
git reset  --hard|soft HEAD~n   -> Quay về trước n commit so với HEAD.

Với option: --hard: Di chuyển HEAD trỏ đến commit đã chỉ định và đặt lại trạng thái làm việc (working directory) để trạng thái của bạn trở về trạng thái của commit đã chỉ định. Các thay đổi chưa được commit sẽ mất.

Với option: --soft: Di chuyển HEAD trỏ đến commit đã chỉ định, nhưng không thay đổi trạng thái làm việc (working directory). Nên sử dụng option này**.

Khi nào nên dùng tùy chọn --hard hay --soft ?

  1. Khi bạn muốn xóa các thay đổi chưa được commit trong trạng thái làm việc thì hãy dùng --hard.
  2. Trong khi --soft để duy trì các thay đổi chưa được commit trong trạng thái làm việc và chỉ đặt lại chỉ số. Ngoài ra, có thể gộp các commit bằng tùy chọn --soft vì tùy chọn này giữ lại các thay đổi chưa được commit trong các trạng thái làm việc của các commit sau nó. **

GIT REVERT

Git revert được sử dụng để tạo một commit mới, mà commit này sẽ loại bỏ các thay đổi đã được thực hiện trong một hoặc nhiều commit trước đó, và áp dụng các thay đổi đó vào nhánh hiện tại.

git revert <hash_commit>
# -- <hash_commit> là mã của 1 commit bất kỳ. Có thể thay thế <hash_commit> bằng HEAD, HEAD^, HEAD~n tương tự ở phần GIT RESET.
# -- Thường sử dụng
git revert  --hard|soft HEAD^    -> Quay về commit trước đó.
git revert  --hard|soft HEAD~1   -> Quay về trước 1 commit so với HEAD. Tương tự HEAD^
git revert  --hard|soft HEAD~2   -> Quay về trước 2 commit so với HEAD.
git revert  --hard|soft HEAD~n   -> Quay về trước n commit so với HEAD.

Chú ý: Git revert sẽ tạo ra một commit mới chứa các thay đổi để hoàn tác các thay đổi của commit đã chỉ định và giữ lại lịch sử commit trước đó. Trong khi đó git reset thì xóa lịch sử commit đi.

Vậy khi nào nên dùng git reset, khi nào nên dùng git revert?

  1. git reset khi bạn muốn xóa các commit và thay đổi liên quan khỏi lịch sử commit và không quan tâm đến lịch sử commit ban đầu.
  2. git revert khi bạn muốn hoàn tác các thay đổi của một hoặc nhiều commit trong lịch sử commit và duy trì lịch sử commit chính xác của dự án để mọi người tiện theo dõi.

GIT REBASE

Git rebase được sử dụng để điều chỉnh lịch sử commit bằng cách di chuyển, sắp xếp các commit từ một nhánh vào nhánh khác.

git rebase <branch_name>
# -- <branch_name> là nhánh mà bạn muốn lấy các commit từ nó và áp dụng lên nhánh hiện tại.

Quá trình rebase sẽ di chuyển các commit trên nhánh hiện tại và đặt chúng lên đầu của nhánh .

Cách hoạt động:

  1. Git tìm các commit trên nhánh hiện tại mà không có trên nhánh .
  2. Git tạo 1 chuỗi tạm thời các commit đó.
  3. Git đặt nhánh hiện tại ở commit cuối cùng của .

Minh họa:

Giả sử rằng ta có lịch sử commit của 2 nhánh main và topic như hình dưới. nhánh topic được checkout từ commit B của nhánh main.

Sau khi ta rebase nhánh main vào nhánh topic thì lịch sử commit sẽ thay đổi như sau:

Nếu xảy ra conflicts giữa các commit, bạn phải xử lý chúng trong quá trình rebase.

Ví dụ

Ta có các commit ở trên nhánh hiện tại như hình dưới:img

Ta có các commt ở trên nhánh main như hình dưới:img

Giờ ta sẽ rebase nhánh main vào nhánh này bằng:

git rebase main

Ta sẽ thu được kết quả như sau: img

Ta thấy 1 commit với message là Add the view ở main đã được thêm vào danh sách các commit ở nhánh này.

Chú ý: Lệnh git rebase có thể gây ra xung đột và thay đổi lịch sử commit Vì vậy khi sử dụng git rebase, hãy cẩn thận và hiểu rõ tác động của nó đối với dự án.

GIT MERGE. Merger 2 branch lại với nhau

Ví dụ: Hiện nay ta đang ở branch_B và ta muốn merge code từ branch_A vào branch_B. Ta sẽ thực hiện các bước

# -- Update source mới nhất từ server vào các branch hiện có trên local
git fetch
# -- Hay update cụ thể một branch
git fetch <branch_name>
# OR ở đây là "git fetch branch_A"
# -- Chuyển qua branch_B nếu cần
git checkout branch_B
# -- Tại branch_B tiến hành gọi merge branch_A vào
git merge branch_A
# -- Xem trạng thái, fix lỗi nếu có
git status
# -- Nếu không có lỗi hay khi fix lỗi xong, tiến hành đưa code sau khi merger lên server
git add .
git commit -m "after merger"
git push

GIT MERGE vs GET REBASE

  • Git merge sẽ chuyển toàn bộ commit ở branchB vào branchA, tạo ra 1 commit thông báo merged thành công, thứ tự commit theo thời gian.
  • Git rebase sẽ chuyển toàn bộ commit ở branchB vào branchA, không tạo ra commit merged, thứ tự commit tùy thuộc cách áp dụng rebase.

Resolve the conflict when MERGE

Chỉnh sửa file manual

Xử lý lỗi khi pull code về từ server. Code này có thể sẽ conflict với code chúng ta đang phát triển

# -- Pull code từ server
git pull
# -- Xem status để thấy các file conflict
git status
# -- Edit file
vi <conflict_file>

Các phần conflict trong file bắt đầu bằng <<<<<<< HEAD kết thúc bằng >>>>>>> phân cách với nhau bằng =======

<<<<<<< HEAD
Đây là phần code của mình                      
<div class="header">
<h1>Sample text 1</h1>
</div>
=======
Đây là phần code pull từ server về
<div class="header">
<h1>Sample text 2</h1>
</div>
>>>>>>> feature-branch

Remove các phần khác biệt, chỉnh lại code cho đúng. Lưu lại.

# -- git add
git add index.html
# -- git commit
git commit -m "Updated h1 in index.html"
# -- push lại lên server
git push

Chỉnh sửa file bằng merge tool

# -- Sử dụng git status để xem các file conflict
git status
# -- Mở merge tool
git mergetool
# -- Chúng ta cần define merge tool cần mở ở git config
# Các tool thường sử dụng là vimdiff, nvimdiff, diffmerge

Cấu hình DiffMerge.app trên MAC OSX làm merge tool

Cài đặt

# -- Cài đặt nếu chưa có
# -- Cài từ brew chạy bằng dòng lệnh
brew install --cask diffmerge
# -- Cài từ website https://www.sourcegear.com/diffmerge/downloads.html
# App tại /Applications/DiffMerge.app
# -- Ta tạo 1 đường dẫn file để chạy dòng lệnh
ln -s /Applications/DiffMerge.app/Contents/Resources/diffmerge.sh /usr/local/bin/diffmerge
# -- Kiểm tra
which diffmerge

Cấu hình

git config --global diff.tool diffmerge
git config --global difftool.diffmerge.cmd 'diffmerge "$LOCAL" "$REMOTE"'
git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd 'diffmerge --merge --result="$MERGED" "$LOCAL" "$(if test -f "$BASE"; then echo "$BASE"; else echo "$LOCAL"; fi)" "$REMOTE"'
git config --global mergetool.diffmerge.trustExitCode true
git config --global mergetool.keepBackup false

Chú ý với MAC chip M

# -- Nếu không cài được diffmerge trên chip M thì có thể thay thế bằng opendiff for commandline.
which opendiff
# -- /usr/bin/opendiff
# -- Nếu đã install XCode thì có app FileMerge.App tại
ls -la /Applications/Xcode.app/Contents/Applications/FileMerge.app

Tool miễn phí SourceTree, Visual Studio Code

Chỉnh sửa bằng các chọn file local hay remote

# --  Sửa conflicted_file bằng cách lấy remote repository version, <conflicted_file> == '.' sẽ lấy tất cả các file
git checkout --theirs <conflicted_file>
git add <conflicted_file>
# --  Sửa conflicted_file bằng cách lấy local repository (code của mình), <conflicted_file> == '.' sẽ lấy tất cả các file
git checkout --ours <conflicted_file>
git add <conflicted_file>

Tham khảo

Git Remove Last Commit – How to Undo a Commit in Git

Git Revert Commit – How to Undo the Last Commit

Hiểu cơ bản về GIT RESET, GIT REVERT, GIT REBASE

Tìm hiểu git push force là gì và cách sử dụng đúng

Using Git push force