* [[https://backlogtool.com/git-guide/tw/|連猴子都能懂的Git入門指南]]
* [[https://gitbook.tw/|為你自己學 Git]]
* [[https://ihower.tw/git/|Git 版本控制系統]]
* [[http://sethrobertson.github.io/GitFixUm/fixup.html|On undoing, fixing, or removing commits in git]]
先設定環境帳號。請見
* [[http://plog.longwin.com.tw/my_note-unix/2009/05/15/git-initial-env-setup-2009|Git 基礎設定 (帳號的環境參數設定)]]。
* [[http://blog.gogojimmy.net/2012/01/17/how-to-use-git-1-git-basic/|Git 教學(1) : Git 的基本使用]]
# 設定都存放在 ~/.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 基礎知識請見 [[http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=giteveryone-101022053442-phpapp02|寫給大家的 Git 教學]]。
* [[https://gitbook.tw/chapters/using-git/working-staging-and-repository.html|工作區、暫存區與儲存庫]]
{{https://gitbook.tw/images/using-git/working-staging-and-repository/all-states.png?500}}
* [[https://gitbook.tw/chapters/gitflow/why-need-git-flow.html|Git Flow 是什麼?為什麼需要這種東西?]]
* [[https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/|GitLab Workflow: An Overview]]
* [[https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow|Gitflow Workflow]]
* [[http://www.devops-blog.net/git/git-flow-how-its-used-and-why-you-should|Git-Flow | How it’s used and why you should]]
====== 初始設定 ======
* [[http://sweetme.at/2013/09/13/git-logs-with-color/|Git Logs With Color and Graphs]]
* [[http://codeinthehole.com/writing/a-useful-template-for-commit-messages/|A useful template for commit messages]]
* [[https://chris.beams.io/posts/git-commit/|How to Write a Git Commit Message]]
$ 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"
====== 創建分支 ======
* 預設分支為 master,建立額外分支 dev,並在分支 dev 上開發,避免在 master 上進行試驗性改動。分支 master 主要用來和上游同步。
* [[https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging/|3.2 Git Branching - Basic Branching and Merging]]
* [[https://www.digitalocean.com/community/tutorials/how-to-use-git-branches|How To Use Git Branches]]
* [[http://stackoverflow.com/questions/5531362/why-git-keeps-showing-my-changes-when-i-switch-branches-modified-added-deleted|Why git keeps showing my changes when I switch branches (modified,added, deleted files) no matter if I run git add or not?]]
* [[http://stackoverflow.com/questions/16329776/how-to-keep-a-git-branch-in-sync-with-master|How to keep a git branch in sync with master]]
$ git branch -b dev
====== 切換分支 ======
* 避免切換分支時,將分支 dev 未 commit 的修改帶到分支 master。
* [[https://git-scm.com/book/en/v1/Git-Tools-Stashing|6.3 Git Tools - Stashing]]
$ git stash
$ git checkout master
$ git checkout dev
$ git stash pop
====== 刪除分支 ======
* 分支 dev 合入 master,刪除分支 dev。
$ git branch -D dev
====== 加入提交 ======
$ git add -u :/
====== 重定基準 ======
* 建議先將分支 dev 基於分支 master 做 rebase,再做後續的合併提交。分支 master 負責跟上游同步。
* [[https://git-scm.com/book/en/v2/Git-Branching-Rebasing|3.6 Git Branching - Rebasing]]
* [[https://blog.yorkxin.org/2011/07/29/git-rebase|Git-rebase 小筆記]]
$ git checkout master
$ git pull
$ git checkout dev
$ git rebase master
====== 合併提交 ======
* 在分支 dev 上開發,最後將數個 commit 合併成一個 commit 給 reviewer/committer 審閱。
* [[http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html|squashing commits with rebase]]
* [[https://ariejan.net/2011/07/05/git-squash-your-latests-commits-into-one/|Git: Squash your latests commits into one]]
$ git rebase -i HEAD~4 # 合併最近 4 個 commit
====== 分割提交 ======
* 避免單一 commit 過大,將其分割成數個 commit,各自相對獨立且可測試。
* [[https://emmanuelbernard.com/blog/2014/04/14/split-a-commit-in-two-with-git/|Split a commit in two with Git]]
* [[http://stackoverflow.com/questions/4307095/how-can-i-split-up-a-git-commit-buried-in-history|How can I split up a Git commit buried in history?]]
====== 修改提交訊息或內容 ======
* [[http://stackoverflow.com/questions/179123/how-to-modify-existing-unpushed-commits|How to modify existing, unpushed commits?]]
* [[https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History|7.6 Git Tools - Rewriting History]]
* [[https://ihower.tw/blog/archives/2622|Git 版本控制系統(3) 還沒 push 前可以做的事]]
$ git commit --amend # 修改最近一個 commit 的訊息
====== 刪除提交 ======
* git revert 和 git reset 作用方式不同。git reset 只用在私人分支,git revert 只用在公共分支。
* [[https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting|Reset, Checkout, and Revert]]
* [[https://www.atlassian.com/git/tutorials/undoing-changes|Undoing Changes]]
* [[http://stackoverflow.com/questions/4850717/how-to-cancel-a-local-git-commit|How to cancel a local git commit]]
* [[http://stackoverflow.com/questions/927358/how-to-undo-last-commits-in-git|How to undo last commit(s) in Git?]]
* [[http://stackoverflow.com/questions/1338728/delete-commits-from-a-branch-in-git|Delete commits from a branch in Git]]
$ git reset HEAD~1 # 刪除最近一個 commit,其內容會保留在當前的工作目錄。
# 修改被刪除的最近一個 commit 內容。
$ git commit -c ORIG_HEAD # 重新 commit 被刪除的最近一個 commit,沿用原本的 commit message。
$ git reset --hard HEAD~1 # 刪除最近一個 commit,不保留其內容。
====== 子模組 ======
* [[https://git-scm.com/book/zh-tw/v1/Git-%E5%B7%A5%E5%85%B7-%E5%AD%90%E6%A8%A1%E7%B5%84-Submodules|6 Git 工具 - 子模組 (Submodules)]]
* `git submodule update --init` 下載之後,進入 submodule 會發現它們不在各自的 master branch。這是因為基本上 parent repo 只用 commit 號來認這些 submodule。
* [[http://josephj.com/entry.php?id=357|Git Submodule 的常見錯誤]]
* [[https://yodalee.blogspot.com/2018/01/git-submodule.html|使用 git submodule 管理 project 所需的其他模組]]
* [[https://blog.wu-boy.com/2011/09/introduction-to-git-submodule/|Git Submodule 介紹與使用]]
====== 發送補丁 ======
* [[http://alblue.bandlem.com/2011/12/git-tip-of-week-patches-by-email.html|Git Tip of the Week: Patches by Email]]
* [[https://git-scm.com/blog/2010/03/10/bundles.html|Git's Little Bundle of Joy]]
* [[http://stackoverflow.com/questions/3635952/how-to-use-git-bundle-for-keeping-development-in-sync|How to use git-bundle for keeping development in sync?]]
$ 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
* [[http://crazycode.iteye.com/blog/311564|使用git bisect快速定位引入错误的版本]]
* [[http://lists.gnu.org/archive/html/qemu-devel/2012-02/msg02856.html|[Qemu-devel] [PATCH] Fix dependency issue introduced by commit 7b93fadf3a38d1ed65ea5536a52efc2772c6e3b8]]
* [[http://lists.gnu.org/archive/html/qemu-devel/2012-02/msg02917.html|[Qemu-devel] [PATCH v2] Fix dependency issue introduced by commit 7b93fadf3a38d1ed65ea5536a52efc2772c6e3b8]]
====== 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
* [[http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git/|How to create and apply a patch with Git]]
* [[http://blog.longwin.com.tw/2009/05/git-send-patch-commit-use-email-2009/|Git 透過 Email 傳送 Patch / Commit]]
* [[http://morefedora.blogspot.com/2009/02/configuring-git-send-email-to-use-gmail.html|Configuring git send-email to use Gmail SMTP]]
* [[http://weylan.blog.edu.cn/2010/546263.html|git-sendmail 好方便]]
* [[http://felipec.wordpress.com/2009/10/25/git-send-email-tricks/|git send-email tricks]]
* [[http://people.debian.org.tw/~chihchun/2010/12/01/sending-patch-with-git-imap-send/|用 git-imap-send 送 patch]]
* [[http://search.cpan.org/~pmakholm/Encode-IMAPUTF7-1.05/lib/Encode/IMAPUTF7.pm|Encode::IMAPUTF7 ]]
* [[http://webcache.googleusercontent.com/search?q=cache:uFhyPoLv9lkJ:blog.rmi.twbbs.org/2010/02/gmail-git-email-git-send-email-smtp.html+&cd=2&hl=zh-TW&ct=clnk|使用 gmail 做為 git-email (git-send-email) 的 smtp server]]
* [[http://elinux.org/Git_usage#send-email|Git usage]]
* [[http://oss.oracle.com/osswiki/GitRepositories|Git Repositories on oss.oracle.com]]
* [[http://linux.die.net/man/1/git-format-patch|git-format-patch]]
* [[http://wiki.qemu.org/Contribute/SubmitAPatch|SubmitAPatch]]
* [[https://lists.gnu.org/archive/html/qemu-devel/2011-09/msg02786.html|[Qemu-devel] [PATCH] exec.c: Remove useless comment]]
* [[https://lists.gnu.org/archive/html/qemu-trivial/2011-10/msg00059.html|[Qemu-trivial] [PATCH] exec.c: Remove useless comment
]]
* [[http://lists.nongnu.org/archive/html/qemu-devel/2011-10/msg03163.html|Re
: [Qemu-devel] [Qemu-trivial] [PATCH] exec.c: Remove useless comment]]
* [[http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg01025.html|Re: [Qemu-devel] [PATCH 0/6] Remove libqemu related stuff from QEMU source tree]]
* [[http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg01549.html|[Qemu-devel] [PATCH 0/6 v2] Remove libqemu related stuff from QEMU source tree]]
* [[http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg02038.html|[Qemu-devel] [PATCH v3 0/6] Remove libqemu related stuff from QEMU source tree]]
* [[http://lists.nongnu.org/archive/html/qemu-trivial/2011-11/msg00036.html|[Qemu-trivial] [PATCH] linux-user/main.c: Add option to user-mode emulation so that user can specify log file name]]
* qemu-trivial@nongnu.org
* [[http://lists.gnu.org/archive/html/qemu-devel/2012-05/msg01958.html|[Qemu-devel] Posting a patch?]]
* [[http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg01989.html|[Qemu-devel] [PATCH v5 1.0] configure: build position independent executables across for x86 hosts]]
* [[http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg00117.html|[Qemu-devel] [PATCH v4 0/4] -net bridge: rootless bridge support for qemu]]
* 學怎麼寫 v? 的不同。
* 單一 patch 在 "---" 後加上 v? 的說明。
Signed-off-by: Avi Kivity
---
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
* [[http://osdir.com/ml/git/2009-09/msg01492.html|'git am' doubt]]
* [[http://linux.yyz.us/git-howto.html|Kernel Hackers' Guide to git]]
====== 常用 Git 服務 ======
* [[https://www.gerritcodereview.com/|Gerrit]]
* rebase 保留舊有的 Changed-Id,就會維持在同一個 code review。
* [[https://www.phacility.com/|Phabricator]]
===== GitHub =====
建議邊閱讀邊實際操作。
* [[https://guides.github.com/activities/hello-world/|Hello World 10 minute read]]
* [[https://help.github.com/articles/which-remote-url-should-i-use/|Which remote URL should I use?]]
* 官方建議使用 HTTPS clone repository。如果不想重複輸入帳號密碼,請見 [[https://help.github.com/articles/caching-your-github-password-in-git|Caching your GitHub password in Git]]。
$ git config --global credential.helper osxkeychain
* [[http://hisham.hm/2016/01/01/how-to-make-a-pull-request-on-github-a-quick-tutorial/|How to make a pull request on GitHub - a quick tutorial]]
* 利用 pull request 貢獻代碼到別人的 repository。
* [[https://www.peterdavehello.org/2014/02/update_forked_repository/|更新從 GitHub 上 fork 出來的 repository (或是同步兩個不同 server 端的 repository)]]
* 發起 pull request 要先 fork 別人的 repository。
* [[https://gist.github.com/longtimeago/f7055aa4c3bba8a62197|How to squash commits in a GitHub pull request]]
* 如果已經發送 pull request 的 commit 需要修改,一般會透過 squash 將更新的 commit 和原來已發送 pull request 的 commit 合併。流程如下:
# 和上游同步
$ git fetch upstream
# 切換到自己的分支
$ git checkout b
$ git rebase -i upstream/master
# 修改後,透過 git rebase -i HEAD~2 squash commit
# 覆寫自己 GitHub 上的分支 b。之前已發送的 pull request 會自動更新。
$ git push origin b -f
* [[https://www.smashingmagazine.com/2014/08/build-blog-jekyll-github-pages/|Build A Blog With Jekyll And GitHub Pages]]
* 透過網頁介面 commit ''_config.yml'' 觸發 GitHub 產生頁面。
* [[https://help.github.com/articles/what-is-github-pages/|What is GitHub Pages?]]
* [[https://medium.com/@cwRichardKim/put-your-resume-pdf-on-a-website-that-updates-automatically-242ef7d023ec#.oyl0ieyod|Put your resume.pdf on a website that updates automatically]]
* 將履歷放上 GitHub,統一維護。
* gh-page 設定好之後,只需更新 master 分支上的履歷。
* [[https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/|Adding an existing project to GitHub using the command line]]
* 在 GitHub 上新建一個不含任何檔案的 repository,會跳出操作提示頁面。
===== GitLab =====
* [[https://about.gitlab.com/|GitLab]]
* [[https://www.youtube.com/watch?v=enMumwvLAug|Introduction to GitLab Workflow]]
* [[https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/|GitLab Workflow: An Overview]]
* [[https://docs.gitlab.com/ce/workflow/README.html|Workflow - GitLab Document]]
* 提供 code review, issue tracker 和 wiki。
流程:
- 開 issue
- 開 branch
- git clone branch; git push; git push -f (類似 gerrit changed-id 的效果)
- 送 merge request
===== Phabricator =====
Phabricator 基本上一個 revision 就是一個 commit。如果當前任務需要多個 commit 完成,創建 dependent revision。
* [[https://medium.com/fcamels-notes/%E4%BD%BF%E7%94%A8-phabricaor-%E7%9A%84%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B-5247b04dd871|使用 Phabricator 的工作流程]]
* [[https://willdemaine.ghost.io/a-simpler-phabricator-stacked-diff-workflow/|A Simpler Phabricator Stacked Diff Workflow]]
* [[https://smacleod.ca/posts/commit-series-with-phabricator/|Commit Series with Phabricator]]
* [[https://medium.com/@kurtisnusbaum/stacked-diffs-keeping-phabricator-diffs-small-d9964f4dcfa6| Stacked Diffs: Keeping Phabricator Diffs Small]]
* 一個 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
====== 外部連結 ======
* [[http://stackoverflow.com/questions/115983/how-do-i-add-an-empty-directory-to-a-git-repository|How do I add an empty directory to a git repository]]
* [[http://www.youtube.com/watch?v=j45cs5_nY2k|Contributing with Git]]
* [[http://blog.longwin.com.tw/2009/01/how-send-code-into-open-source-project-diff-patch-2009/|好文: 如何將程式送給 Open Source 的 Project 與 diff / patch 使用]]
* [[http://ihower.tw/blog/archives/6696/|Git 教育訓練課程投影片]]