先設定環境帳號。請見

# 設定都存放在 ~/.gitconfig
$ git config --global user.name "陳韋任 (Wei-Ren Chen)"
$ git config --global user.email chenwj.cs97g@g2.nctu.edu.tw

origin(remote) 是遠端伺服器上的倉儲; master(branch) 是本地端正在修改的分支,master 是預設的分支名稱。關於 Git 基礎知識請見 寫給大家的 Git 教學

初始設定

$ git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative"

創建分支

$ git branch -b dev

切換分支

$ git stash
$ git checkout master
$ git checkout dev
$ git stash pop

刪除分支

  • 分支 dev 合入 master,刪除分支 dev。
$ git branch -D dev

加入提交

$ git add -u :/

重定基準

$ git checkout master
$ git pull
$ git checkout dev
$ git rebase master

合併提交

$ git rebase -i HEAD~4 # 合併最近 4 個 commit

分割提交

修改提交訊息或內容

刪除提交

$ git reset HEAD~1 # 刪除最近一個 commit,其內容會保留在當前的工作目錄。
# 修改被刪除的最近一個 commit 內容。
$ git commit -c ORIG_HEAD # 重新 commit 被刪除的最近一個 commit,沿用原本的 commit message。
$ git reset --hard HEAD~1 # 刪除最近一個 commit,不保留其內容。

子模組

發送補丁

$ git bundle create commits.bundle commit_id..master # commit_id 之後包含你想要打包的 commit。
# 透過 email 或是 usb 傳送給對方。
$ git remote add commits /path/to/commits.bundle # 添加來自 commmits.bundle 的 remote。
$ git pull commits dev # 如果對方是在分支 dev 打包 bundle,則指從分支 dev pull。  

Bisect

$ git clone git://git.qemu.org/qemu.git
# 开始 git bisect。
$ git bisect start
# 标记当前版本为错误。
$ git bisect bad
# 標記一個只知好的版本,git 會自動選出一個中間版本,重新開始測試。
$ git bisect good v1.0.1
# 測試通過,標記為 good,選下一個中間版本。如果失敗,標記成 bad,選下一個中間版本。
$ git bisect good
# 顯示引入錯誤的 commit 其內容。
$ git show 7b93fadf3a38d1ed65ea5536a52efc2772c6e3b8
 
  ... 定位到引入錯誤的 commit,修正 ...
 
# 返回到当前的 HEAD。
$ git bisect reset

Submit Patch

# git clone git://repo.or.cz/qemu.git
$ git clone git://git.qemu.org/qemu.git
$ cd qemu
# 建立新的 branch,之後會自動生成 a 和 b 的 diff。
$ git checkout -b b
 
... 修改檔案 ...
 
# 生成單一 patch
$ git commit -a -m "exec.c: Remove useless comment" # 此訊息會是之後信件的 subject
# 生成多個 patch。google git split patch
$ git commit exec.c -m "exec.c: Make variable logfilename accessible from linux-user/main.c"
$ git commit linux-user/main.c -m "linux-user/main.c: Add option to user-mode emulation so that user can specify log file name"
$ git fetch origin
$ git rebase origin
# 產生單一 patch
$ git format-patch -s origin --stdout > ../b.patch
$ mutt -H b.patch
# 產生多個 patch。--cover-letter 會產生 patchset 的第一封信,應該用來描述 patchset 的大致用途。
$ git format-patch -s origin --cover-letter  -o tmp; cd tmp
# 書寫 patch set 的開頭第一封信,並依序填寫 patch set 的內文解釋 patch。
# --compose 內文為空,沒有任何跟 patchset 有關的東西,和 cover letter 不一樣。
# 可以直接用 vim 修改 patch,且之前修改的內容都會留下。
#
# 建議先改完,在 git send-email --annotate --suppress-from --to user@example.com * 一次送出。
#
$ git send-email --annotate --suppress-from --to user@example.com 0000-cover-letter.patch
Subject: [Qemu-trivial][PATCH 0/2] Add option to user-mode emulation so that user can specify log file name 
 
  QEMU user-mode's default log file name is "/tmp/qemu.log". In order to change
the log file name, user need to modify the source code then recompile QEMU. This
patchset allow user use "-D filename" option to specify the log file name.
 
Chen Wen-Ren (2):
  exec.c: Make variable logfilename accessible from linux-user/main.c
  linux-user/main.c: Add option to user-mode emulation so that user can
    specify log file name
 
 exec.c            |    2 +-
 linux-user/main.c |    8 ++++++++
 2 files changed, 9 insertions(+), 1 deletions(-)
 
--
1.7.3.5
# 會送到 gmail 草稿夾
$ git format-patch --attach --stdout origin | git imap-send
    • 學怎麼寫 v? 的不同。
    • 單一 patch 在 "—" 後加上 v? 的說明。
      Signed-off-by: Avi Kivity <address@hidden>
      ---
      
      v5: fix typos; only default enable for x86; mutually exclusive with -static
      
      v4: say it's v4 and for 1.0
      
      v3: detect toolchain support for PIE at configure time
      
      v2: improve description to include relro
    • 多個 patch,在 cover letter 上加上 v? 的說明。
      v4:
       - Update has_vnet_hdr() to return bool
       - Update helper's main() to prevent errno clobbering
       - Let Kernel cleanup helper's file descriptors
      
      Corey Bryant (4):
        Add basic version of bridge helper
        Add access control support to qemu bridge helper
        Add cap reduction support to enable use as SUID
        Add support for net bridge

Apply Patch

# 查看 patch 但不 apply
$ git apply --stat b.patch
 exec.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)
# apply patch
$ git apply --check b.patch
# 保留 patch 的資訊
$ git am --signoff b.patch
$ git log
# 使用 mutt 把包含 patch 的 mail 存到 mbox,下 s。例如存到 qemu-patch。
$ git am --utf8 --signoff ../qemu-patch
cat: /z/tmp/chenwj/qemu/.git/rebase-apply/last: No such file or directory
previous rebase directory /z/tmp/chenwj/qemu/.git/rebase-apply still exists but mbox given.
$ git am --abort
$ git am --utf8 --signoff ../qemu-patch

常用 Git 服務

    • rebase 保留舊有的 Changed-Id,就會維持在同一個 code review。

GitHub

建議邊閱讀邊實際操作。

GitLab

流程:

  1. 開 issue
  2. 開 branch
  3. git clone branch; git push; git push -f (類似 gerrit changed-id 的效果)
  4. 送 merge request

Phabricator

Phabricator 基本上一個 revision 就是一個 commit。如果當前任務需要多個 commit 完成,創建 dependent revision。
  • 一個 branch,一個 commit,一個 review 單。
    # 依賴關係: master -> ref_abc -> fix_abc
    (master)  $ git checkout -b ref_abc
    (ref_abc) $ git commit
    (ref_abc) $ git checkout -b fix_abc
    (fix_abc) $ git commit
    (fix_abc) $ git checkout ref_abc
    (ref_abc) $ arc diff master      # D1
    (ref_abc) $ git checkout fix_abc
    (fix_abc) $ arc diff ref_abc     # D2
  • 更新 review 單。
    (master)  $ git checkout ref_abc
    (ref_abc) $ git pull --rebase origin master
    (ref_abc) $ git submodule update
    (ref_abc) $ git commit -a --amend
    (ref_abc) $ arc diff master --update D1
    (ref_abc) $ git checkout fix_abc
    (fix_abc) $ git pull --rebase . ref_abc
    (fix_abc) $ git commit -a --amend
    (fix_abc) $ arc diff ref_abc --update D2
  • approve 之後,由前往後依序合入代碼。
    (master)  $ git checkout ref_abc
    (ref_abc) $ arc land --onto master --revision D1 --merge
    (ref_abc) $ git checkout fix_abc
    (fix_abc) $ arc land --onto master --revision D2 --merge

外部連結

登录