Git notes

git
git

Git là phần mềm dùng để quản lý và kiểm tra các phiên bản khác nhau trong quá trình phát triển mã nguồn. Tôi thường sử dụng Git để quản lý code cũng như để hoàn thành luận văn gần đây của mình. Trong bài viết này, tôi xin tổng hợp lại ghi chú các thao tác lệnh thường dùng trong Git.

Cơ chế của Git

Git architecture
Git architecture
  • repository (nơi lưu thông tin quá khứ/cuối cùng của dự án, commit từ staging index).
  • staging index (nơi lưu tạm dữ liệu trước khi commit).
  • working directory (nơi lưu thông tin làm việc hiện hành)
  • Con trỏ HEAD luôn trỏ vào thời điểm cuối cùng của nhánh hiện hành.

Quy trình làm việc nhóm với Git

# My work
git checkout master
git fetch
git merge origin/master
git checkout -b feedback_form
git add feedback.html
git commit -m "Add customer feedback form"
git fetch
git push-u origin feedback_form

# Coworker
git checkout master
git fetch
git merge origin/master
git checkout -b feedback_form origin/feedback_form
git log
git show 8284abdq9
git commit -am "Add tour selector to feedback form"
git fetch
git push

# My work
git fetch
git log -p feedback_form..origin/feedback_form
git merge origin/feedback_form
git checkout master
git fetch
git merge origin/master
git merge feedback_form
git push

Ta có thể thấy quy trình làm việc này khá công phu, nhưng theo thời gian ta sẽ hình thành được thói quen và cách làm việc nhóm hiệu quả hơn nhờ Git. Những thao tác này sẽ được trình bày với các nội dung bên dưới.

Thao tác commit

Sau mỗi lần thay đổi nội dung của file, ta thực hiện các lệnh sau

# đưa các file bị thay đổi vào staging index
git add .

# lưu vào repository kèm theo thông tin ghi chú
git commit -m "Initial commit"

# add và commit cùng lúc
git commit -am "Initial commit"

# thay đổi nội dung ghi chú hoặc ghi đè lên commit
# gần nhất
git commit --ammend "Ammend the commit"

Kinh nghiệm viết thông tin ghi chú

  • Một dòng mô tả rõ ràng và ngắn gọn, khoảng 50 kí tự đổ xuống.
  • Viết nội dung ở thì hiện tại, không phải ở thì quá khứ. (e.g. fix bug, fixes bug, not fixed bug)
  • Có thể sử dụng tiếp đầu ngữ để quản lý (e.g. [css, js], bugfix:, #38405-)

Quan sát

Quan sát commit log

# liệt kê danh sách commit
git log

# liệt kê 2 commit gần nhất
git log -n 2
git log -2

# liệt kê theo thời gian "kể từ"
git log --since=2015-12-01

# liệt kê theo thời gian "tới khi"
git log --until=2015-12-01

# liệt kê theo người commit
git log --author="ongxuanhong"

# tìm theo regular expression
git log --grep="Init"

# liệt kê theo định dạng một dòng đơn giản
git log --oneline

# liệt kê trong khoảng hai thời điểm
git log 29910a..92ad92

# liệt kê trong khoảng đối với file xác định
git log 09ua199.. index.html

# liệt kê theo dạng đồ thị
git log --oneline --graph --all --decorate

# hiển thị nội dung commit
git show

# hiển thị nội dung remote branch origin/master
git log --oneline origin/master
git graph
git graph

Quan sát những thay đổi

# so sánh sai biệt giữa working directory và repository
git diff

# so sánh sai biệt giữa staging index và repository
git diff --staged

# xem những thay đổi của một file xác định
git diff first_file.txt

# so sánh sai biệt giữa một thời điểm commit trong
# quá khứ với repository
git diff 9a98bc98

# xem những thay đổi của một file xác định tại một
# thời điểm commit bất kì
git diff 9a98bc98 first_file.txt

# rút gọn hiển thị những thay đổi
git diff --color-words first_file.txt

# so sánh sai biệt giữa hai commit bất kì
git diff 9a98bc98..1737vb8a72

# thống kê những thay đổi từ thời điểm bất kì trong
# quá khứ cho đến thời điểm hiện tại
git diff --stat --summary d54cf21..HEAD

# so sánh hai branch
git diff master..new_branch

# so sánh branch new_feature với commit trước đó
# của shorten_title branch
git diff --color-words new_feature..shorten_title^

# so sánh local branch với tracking branch origin/master
git diff master..origin/master

Thao tác với file

Loại bỏ deleted/untracking file

# xác nhận loại bỏ một file đã delete
git rm file_to_delete1.txt

# xác nhận loại bỏ một loạt file đã delete
git ls-files --deleted -z | xargs -0 git rm

# loại bỏ một file untrack
git clean -f trunk_1.txt

Di chuyển hoặc đổi tên file

# đổi tên file
git mv first_file.txt primary_file.txt

# di chuyển và đổi tên file cùng lúc
git mv second_file.txt source/secondary_file.txt

Git reset

Độ sâu sự can thiệp của Git reset bắt đầu từ repository

  • soft: không thay đổi staging index và working directory
  • mixed (default): thay đổi staging index khớp với repostitory nhưng không thay đổi working directory
  • hard: thay đổi staging index và working directory khớp với repository
# quan sát SHA index mà HEAD đang trỏ vào
cat .git/refs/heads/master

# di chuyển con trỏ của repository đến một thời điểm
# trong quá khứ
git reset --soft da9u0388787

Undo những thay đổi

# mới thay đổi ở working directory, chưa add vào staging index,
# ta checkout nội dung quá khứ từ repository về working
# directory để undo những thay đổi.
git checkout -- index.html

# unstaged những thay đổi: đưa staging index về với trạng thái
# quá khứ của repository
git reset HEAD resources.html

# truy vấn phiên bản tại một thời điểm commit trong quá khứ
git checkout 83872763a776 -- resources.html

# quay lại phiên bản trong quá khứ, đồng thời thực hiện
# một commit mới kèm theo ghi chú
git revert 83872763a776

Git ignore

Những file thường không cần track

  • Compiled source code
  • Packages và compressed files
  • Logs và databases
  • Những file phát sinh từ hệ điều hành
  • User uploaded assets (images, PDFs, videos)

Branch

git branch
git branch
  • Dùng để thử ý tưởng mới
  • Cô lập tính năng mới với tính năng chính
  • Linh hoạt chuyển đổi giữa các tính năng
  • Chỉ dùng một working directory nhưng có thể lưu được nhiều pha làm việc cùng lúc.

Xem và tạo lập branch

# liệt kê danh sách các branch
git branch

# xem con trỏ HEAD đang ở branch nào
cat .git/HEAD

# xem có bao nhiêu branch trong head
cat .git/refs/heads/

# head đang trỏ đến commit nào
cat .git/refs/heads/master

# tạo lập branch mới
git branch new_branch

Switching

Để chuyển đổi qua lại giữa các branch, mọi thay đổi trong working directory phải được commit hoặc có thể tồn tại một số file untrack.

# chuyển qua branch new_branch
git checkout new_branch

# vừa tạo vừa chuyển qua new_branch cùng lúc
git checkout -b new_branch

Trường hợp chuyển đổi nhưng bị vướng uncommit

# cách 1: undo những thay đổi
git checkout -- index.html

# cách 2: commit các thay đổi còn tồn tại
git commit -am "Commit changes"

# cách 3: lưu tạm vào stash (nơi lưu trữ bí mật)
git stash save "changed mission page title"

Làm việc với stash

# hiển thị danh sách stash đã lưu
git stash list

# quan sát nội dung của stash cụ thể, index bắt đầu từ 0
git stash show stash@{0}

# patch option: tương tự như show commit
git stash show -p stash@{0}

# lấy stash ra và đưa vào working directory
# pop: xóa luôn khỏi thư mục stash
# apply: chỉ copy từ thư mục stash
git stash pop/apply stash@{0}

# xóa stash
git stash drop stash@{0}

# xóa tất cả stash
git stash clear

Thay đổi branch

# Đổi tên branch
git branch -m/--move new_feature seo_title

# Phải switch qua branch khác trước khi xoá.
# Ta không thể xóa branch hiện hành. Tương tự như việc
# chương trình đang đọc file thì chương trình khác không
# được xóa.
git branch -d/--delete branch_to_delete

# Nếu branch muốn xóa không chứa nội dung nào,
# thì ta chỉ cần tham số -d để xóa. Ngược lại, ta phải merge
# nội dung trước khi xoá hoặc ta có thể dùng tham số -D
# để chấp nhận xóa hoàn toàn
git branch -D branch_to_delete

Thay đổi dấu nhắc lệnh của command line để quan sát branch hiện hành

# mở file .bashrc, sau đó thêm dòng lênh
export PS1='\W$(__git_ps1 "(%s)") > '

# nạp lại .bashrc để thấy kết quả
source .bashrc

# kết quả thu được
testing(new_branch) >

Merge branch

Fast-forward merge: di chuyển nội dung commit từ new_branch đưa trực tiếp lên timeline của master sau đó di chuyển con trỏ HEAD vào vị trí mới. Phương thức này không cần tạo commit mới.

Real merge: merge nội dung hai branch có nội dung khác nhau kèm theo một commit mới.

# chuyển qua branch chính (có thể branch khác ngoài master)
git checkout master

# merge branch
git merge revise_navigation

# ép Git không sử dụng fast-forward mà phải tạo một commit mới
git merge --no-ff revise_navigation

# nếu fast-forward được thì làm, không được thì thôi
git merge --ff-only revise_navigation

Giải quyết merge conflict

merge conflicts
merge conflicts

Merge conflict xảy ra khi nội dung trên cùng một file có nhiều hơn một sự thay đổi diễn ra cùng lúc. Lúc này, Git sẽ không biết nên chọn nội dung nào để làm nội dung lưu lại cuối cùng.

Khi merge conflict, bên trong nội dung file bị conflict sẽ có các dòng đánh dấu như bên dưới

<<<<<<<<<< HEAD
some content A

======
some content B

>>>>>>>>>> text_edits

Lúc này ta có 3 cách giải quyết

# 1) không merge nữa
git merge --abort

# 2) lựa chọn và chỉnh sửa nội dung, sau đó commit.
# default message của merge sẽ hiện ra
git add .
git commit

# 3) sử dụng merge tool
git mergetool
'git mergetool' will now attempt to use one of
the following tools: meld opendiff kdiff3 tkdiff
xxdiff tortoisemerge gvimdiff diffuse diffmerge
ecmerge p4merge araxis bc3 codecompare emerge vimdiff

# sau khi merge, ta có thể quan sát branch hiện hành
# đã merge với những branch nào
git branch --merged

Để hạn chế merge conflict

  • chỉ nên thay đổi một vài dòng
  • chỉ nên thay đổi trên một file
  • chú ý các thay đổi như space, tab, line return
  • thường xuyên merge (thay vì đợi conflict 50 file, ta hạn chế conflict còn 2-3 file).

Git remote

Git remote dùng để chia sẻ source code cho các thành viên trong nhóm cùng làm việc. Ba bước cơ bản thường dùng để thao tác với remote gồm push (upload source code), fetch (download source code), merge (đồng bộ hóa dữ liệu server và local). Trong đó, con trỏ orgin/master cũng chỉ là một branch để tracking luân phiên server và local.

git push
git push
git fetch
git fetch
git merge
git merge

Sau khi tạo một tài khoản trên Github hoặc Bitbucket ta có thể tiến hành tracking remote server.

Thêm/Xóa một remote

# liệt kê danh sách remote đang tracking (tương tự git branch
# liệt kê danh sách các branch)
git remote

# liệt kê chi tiết thông tin fetch/push
git remote -v

# thêm một remote
git remote add <alias> <url>
git remote add origin https://github.com/username/project.git

# nơi lưu thông tin remote
cat .git/config

# xóa một remote
git remote rm origin

Tạo remote branch

# -u: upstream. pushing branch master lên remote origin
git push -u origin master

# nơi lưu thông tin origin/master
cat .git/refs/remotes/origin/master

# xem danh sách remote branch
git branch -r

# xem danh sách cả remote và local branch
git branch -a

# download thành một thư mục mới
git clone https://github.com/username/project.git new_folder

Tracking remote branch

# cách 1: chỉnh config file
git config branch.non_tracking.merge refs/heads/master
git config branch.non_tracking.remote origin

# cách 2: dùng --set-upstream (Git > 1.7)
git branch --set-upstream non_tracking origin/master

Pushing > Fetching > Merging

# upload master branch lên remote origin
git push origin master

# full version (local_branch:remote_branch)
git push origin master:master

# phiên bản rút gọn: vì ta đang tracking origin
# trên master branch
git push

# download source từ remote origin
git fetch origin

# phiên bản rút gọn: vì ta đang tracking origin
# vài điểm lưu ý: fetch trước khi làm việc, fetch
# trước khi push, fetch thường xuyên
git fetch

# đồng bộ local và remote
git merge origin/master

# pull thay thế hai bước fetch và merge, chỉ sử dụng
# khi nắm vững hai cơ chế trên
git pull

Checkout/Delete remote branch

Khi thư mục local chưa có branch trên remote, ta có thể checkout như sau

# checkout remote branch
git branch non_tracking origin/non_tracking

# cách khác: vừa tạo branch vừa switch branch
git checkout -b non_tracking origin/non_tracking

# delete branch trên remote server
# (local vẫn còn non_tracking branch)
# cơ chế: do không có branch nào được push
# nên trên server tự động delete remote branch
git push origin :non_tracking

# cách khác: sử dụng --delete
# non_tracking trên server và local đều được delete
git push origin --delete non_tracking

Một số cách thiết lập alias (shortcut) cho những command hay sử dụng

git config --global alias.st status
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
git config --global alias.df diff
git config --global alias.dfs "diff --staged"
git config --global alias.logg "log --graph --oneline --decorate --abbrev-commit --all"

Lần đầu tạo repository

Thiết lập thông số lần đầu làm việc

git config --global user.name "Hong Ong"
git config --global user.email "my_email@email.com"

Thiết lập repository

Trường hợp chỉ muốn clone repository

git clone ssh://git@github.com:1234/abc/my_project.git

Trường hợp đã có sẵn source code và muốn upload lên repository

cd existing-project
git init
git add --all
git commit -m "Initial Commit"
git remote add origin ssh://git@github.com:1234/abc/my_project.git
git push origin master

Trường hợp Git đã track source của bạn trong quá trình làm việc tại local

cd existing-project
git remote set-url origin ssh://git@github.com:1234/abc/my_project.git
git push origin master
Advertisement

Một suy nghĩ 2 thoughts on “Git notes

Trả lời

Điền thông tin vào ô dưới đây hoặc nhấn vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Đăng xuất /  Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Đăng xuất /  Thay đổi )

Connecting to %s