Git 是現今在軟體業中被廣泛使用的一套分散式版本控制系統軟體,與集中式最大的不同在於,分散式不需要伺服器就可以
運行版本控制,使得軟體開發的交流變得更為簡單快速。
此篇主要是整理 Git 分散式的版本控制系統,從架設、簡易操作、設定、基本操作、遠端操作...等。
註:Git 的範圍太廣了,此篇當作是初學入門就好了!
注意事項
由 project/.git/config 可知:(若有更多,亦可由此得知)
origin(remote)是 Repository 的版本。
master(branch)是 local 端,正在修改的版本。
平常沒事不要去動到 origin,如果動到,可用 git reset --hard 恢復到沒修改的狀態。
用戶設定
# 顯示用戶名。
git config user.name
# 顯示用戶信箱位址。
git config user.email
# 設定本地用戶名。
git config user.name "your_name"
# 設定本地用戶信箱位址。
git config user.email "your_name@example.com"
# 設定全域用戶名。
git config --global user.name "your_name"
# 設定全域用戶信箱位址。
git config --global user.email "your_name@example.com"
初始化與複製專案
# 初始化儲存庫。
git init
# 在當前目錄下複製現有儲存庫。
git clone <url>
# 在遠端庫克隆一個本地庫(Clone an existing repository)
git clone ssh://user@domain.tld/repo.git
Git 新增檔案
# 將資料先暫存到 staging area, add 之後再新增的資料,於此次 commit 不會含在裡面。
git add .
# 新增檔案至暫存區域
git add <file>
# 手動解決衝突使用編輯器並標記已解決的檔案。
git add <resolved-file>
# 新增所有副檔名為 extension 的檔案至暫存區域
git add *.extension
# 修改過的檔案,也要 add. (不然 commit 要加上 -a 的參數)。
git add filename git add modify-file
# 只加修改過的檔案,新增的檔案不加入。
git add -u
# 進入互動模式。
git add -i
Git 刪除檔案
git rm filename
# 取消追蹤並刪除檔案
git rm <file>
# 取消追蹤檔案,把此檔案從過去的提交紀錄中刪除,但是保留目前本地的檔案
(Remvoe file from previous commits but keep it locally)
git rm --cached <file>
# 將未追蹤檔案捨棄
git clean -f -d
Git 修改檔名、搬移目錄
git mv filename new-filename
Git status 看目前的狀態
# 看目前檔案的狀態。
git status
Git Commit
git commit
# 修改提交訊息
git commit --amend
git commit -m 'commit message'
# 將所有修改過得檔案都 commit,但是新增的檔案還是得要先 add.
git commit -a -m 'commit -message'
# -v 可以看到檔案哪些內容有被更改,-a 把所有修改的檔案都 commit
git commit -a -v
Git 產生新的 branch
# 列出目前有多少 branch(顯示本地所有分支)
git branch
# 新增分支
git branch <branch_name>
# 產生新的 branch(名稱:new-branch),若沒有特別指定,會由目前所在的 branch / master 直接複製一份。
git branch new-branch
# 由 master 產生新的 branch(new-branch)
git branch new-branch master
# 由 tag(v1)產生新的 branch(new-branch)
git branch new-branch v1
# 刪除 new-branch,删除一個本地分支(Delete a local branch)
git branch -d new-branch
# 強制刪除 new-branch(強制刪除分支)
git branch -D new-branch
# 更名分支
git branch -m <old_branch_name> <new_branch_name>
# 列出所有 Repository branch
git branch -r
# 列出所有 branch
git branch -a
# 刪除一個遠端分支(Delete a remote branch)
git branch origin --delete <branch>
Git checkout 切換 branch
# 撤銷某次提交的某個檔案的内容(Revert a specific file from a previous commit)
git checkout <commit><file>
# 切換到 branch-name
git checkout branch-name
# 切換到 master
git checkout master
# 從 master 建立新的 new-branch,並同時切換過去 new-branch
git checkout -b new-branch master
# 產生新的 branch,並同時切換過去 new-branch # 與 remote repository 有關。
git checkout -b new-branch test
# 由現在的環境為基礎,建立新的 branch
git checkout -b newbranch
# 於 origin 的基礎,建立新的 branch
git checkout -b newbranch origin
# 還原檔案到 Repository 狀態
git checkout filename
# 將所有檔案都 checkout 出來(最後一次 commit 的版本),注意,若有修改的檔案都會被還原到上一版。
(git checkout -f 亦可)
git checkout HEAD .
# 丟棄此檔案的本地修改(Discard local changes in a specific file)
git checkout HEAD <file>
# 將所有檔案都 checkout 出來(xxxx commit 的版本,xxxx 是 commit 的編號前四碼)注意,若有修改的檔案都會被
還原到上一版。
git checkout xxxx .
# 恢復到上一次 Commit 的狀態(* 改成檔名,就可以只恢復那個檔案)。
git checkout -- *
Git diff
# 與 Master 有哪些資料不同。
git diff master
# 比較 staging area 跟本來的 Repository
git diff --cached
# tag1, 與 tag2 的 diff
git diff tag1 tag2
# tag1, 與 tag2 的 file1, file2 的 diff
git diff tag1:file1 tag2:file2
# 比較目前位置與 staging area(比對工作目錄及暫存區域的差異)
git diff
# 比較 staging area 與 Repository 差異。
git diff --cached
# 比較目前位置與 Repository 差別。
git diff HEAD
# 比較目前位置與 branch(new-branch)的差別。
git diff new-branch
git diff --stat
Git Tag
# 給目前提交打一個 tag,也可以查看目前標籤(Tag the current commit)。
git tag <tag-name>
# log 是 commit ebff810c461ad1924fc422fd1d01db23d858773b 的內容,設定簡短好記得 Tag:v1
git tag v1 ebff
# tag 也可以下中文,任何文字都可以。
git tag 中文 ebff
# 把 tag = 中文 刪掉。
git tag -d 中文
Git log
# 將所有 log 秀出(顯示提交歷史紀錄)。
git log
# 顯示 n 個提交歷史紀錄。
git log -n
# 秀出所有的 log(含 branch)。
git log --all
# 將所有 log 和修改過得檔案內容列出。
git log -p
# 將此檔案的 commit log 和修改檔案內容差異部份列出。
git log -p filename
# 列出此次 log 有哪些檔案被修改。
git log --name-only
# 查每個版本間的更動檔案和行數。
git log --stat --summary
# 這個檔案的所有 log。
git log filename
# 這個目錄的所有 log。
git log directory
# log 裡面有 foo() 這字串的。
git log -S'foo()'
# 不要秀出 merge 的 log。
git log --no-merges
# 最後這 2 週的 log。
git log --since="2 weeks ago"
# 秀 log 的方式
git log --pretty=oneline
# 秀 log 的方式
git log --pretty=short
git log --pretty=format:'%h was %an, %ar, message: %s'
# 會有簡單的文字圖形化,分支等。
git log --pretty=format:'%h : %s' --graph
# 依照主分支排序
git log --pretty=format:'%h : %s' --topo-order --graph
# 依照時間排序
git log --pretty=format:'%h : %s' --date-order --graph
# 這個提交者最後一次的提交日誌(Show changes over time for a specific committer)
git log --author=<committer name>
Git show
# 顯示提交內容
git show <sha>
# 查 log 是 commit ebff810c461ad1924fc422fd1d01db23d858773b 的內容。
git show ebff
# 查 tag:v1 的修改內容。
git show v1
# 查 tag:v1 的 test.txt 檔案修改內容。
git show v1:test.txt
# 此版本修改的資料。
git show HEAD
# 前一版修改的資料。
git show HEAD^
# 前前一版修改的資料。
git show HEAD^^
# 前前前前一版修改的資料。
git show HEAD~4
Git reset 還原
# 退回到某個版本並儲存未追蹤的修改。
git reset <commit>
# 丟棄所有的本地修改(Discard all local changes in your working directory)
git reset --hard HEAD
# 還原到最前面
git reset --hard HEAD
git reset --hard HEAD~3
git reset --soft HEAD~3
# 將檔案從暫存區域中移除
git reset <file>
# 將所有副檔名為 extension 的檔案從暫存區域中移除
git reset *.extension
# 將所有檔案從暫存區域中移除
git reset .
# 將所有已追蹤檔案還原
git reset --hard
# 退回到某個版本(Discarding local changes)
git reset --hard <commit>
# 從 staging area 狀態回到 unstaging 或 untracked(檔案內容並不會改變)。
git reset HEAD filename
# 退回到某個版本並儲存未提交的修改。
git reset --keep <commit>
Git grep
# 查 v1 是否有 "te" 的字串。
git grep "te" v1
# 查現在版本是否有 "te" 的字串。
git grep "te"
Git stash 暫存
# 丟進暫存區(新增暫存)。
git stash
# 列出所有暫存區的資料(顯示查看所有暫存)。
git stash list
# 取出最新的一筆,並移除。
git stash pop
# 取出最新的一筆 stash 暫存資料,但是 stash 資料不移除(提取暫存)。
git stash apply
# 提取特定暫存
git stash apply <stash_name>
# 刪除特定暫存
git stash drop <stash_name>
# 把 stash 都清掉。
git stash clear
Git merge 合併
git merge
# 將 branch_name 合併到目前分支。將其他分支和並到目前分支(Merge branch into your current HEAD)
git merge <branch_name>
git merge master
git merge new-branch
# 使用配置的合並工具解決衝突(Resolve conflicts using your configured merge tool)
git mergetool
Git 版本控制系統(2) 開 branch 分支和操作遠端 repo.x
Straight merge 預設的合併模式,會有全部的被合併的 branch commits 記錄加上一個 merge-commit,看線圖會有兩
條 Parents 線,並保留所有 commit log。
Squashed commit 壓縮成只有一個 merge-commit,不會有被合併的 log。SVN 的 merge 即是如此。
cherry-pick 只合併指定的 commit。
rebase 變更 branch 的分支點:
找到要合併的兩個 branch 的共同的祖先,然後先只用要被 merge 的 branch 來 commit 一遍,然後再用目前 branch
再 commit 上去。這方式僅適合還沒分享給別人的 local branch,因為等於砍掉重練 commit log。
# 以 branch_name 為基底衍合目前分支。
git rebase <branch_name>
# 終止目前合併(Abort a rebase)
git rebase --abort
# 解決衝突後繼續目前合併和重整(Continue a rebase after resolving confilcys)
git rebase --continue
指令操作
# 合併另一個 branch,若沒有 conflict 衝突會直接 commit。若需要解決衝突則會再多一個 commit。
git merge <branch_name>
# 將另一個 branch 的 commit 合併為一筆,特別適合需要做實驗的 fixes bug 或 new feature,最後只留結果。
合併完不會幫你先 commit。
git merge --squash <branch_name>
# 只合併特定其中一個 commit。如果要合併多個,可以加上 -n 指令就不會先幫你 commit,這樣可以多 pick 幾個要合
併的 commit,最後再 git commit 即可。
git cherry-pick 321d76f
# 取得提交內容並提交到當前分支
git cherry-pick <sha>
# 取得合併內容並提交到當前分支
git cherry-pick -m 1 <sha>
Git blame
# 關於此檔案的所有 commit 紀錄。
git blame filename
Git 還原已被刪除的檔案
# 查看已刪除的檔案
git ls-files -d
# 將已刪除的檔案還原
git ls-files -d | xargs git checkout --
Git 維護
# 整理前和整理後的差異,可由:git count-objects 看到。
git gc
git gc --prune
git fsck --full
Git revert 資料還原
# 撤銷某次的提交内容(Revert a commit by providing a new commit with contrary changes)
git revert <commit>
# 回到前一次 commit 的狀態。
git revert HEAD
# 還原提交內容
git revert <sha>
# 回到前前一次 commit 的狀態。
git revert HEAD^
# 從 staging area 狀態回到 unstaging 或 untracked(檔案內容並不會改變)
git reset HEAD filename
# 從 unstaging 狀態回到最初 Repository 的檔案(檔案內容變回修改前)
git checkout filename
Git Rollback 還原到上一版
git reset --soft HEAD^
編輯 + git add filename
git commit -m 'rollback'
以下與 遠端 Repository 相關
Git remote 維護遠端檔案
# 顯示所有遠端儲存庫
git remote
# 顯示所有遠端儲存庫及 URL
git remote -v
# 新增遠端儲存庫並命名為 short_name
git remote add <short_name> <url>
# 加入新的遠端庫(Add new remote repository)
git remote add <remote> <url>
# 移除遠端儲存庫
git remote rm <short_name>
# 更名遠端儲存庫
git remote rename <short_name> <new_name>
# 重命名遠端庫(Rename a remote)
git remote rename <old-name> <new-name>
# 增加遠端 Repository 的 branch(origin -> project)。
git remote add new-branch http://git.example.com.tw/project.git
# 秀出現在有多少 Repository
git remote show
# 查看這個遠端庫的訊息(Show information about a remote)
git remote show <remote>
# 刪掉。
git remote rm new-branch
# 更新所有 Repository branch
git remote update
# 列出所有 Repository branch
git branch -r
# 擷取並合併遠端儲存庫
git pull
# 從遠端庫更新資料並立即合併資料(Download changes and directly merge into HEAD)
git pull <remote><branch>
# 將當前分支上傳到遠端儲存庫
git push <remote_name> <branch_name>
# 將本地資料同步到遠端庫中(Publish local changes on a remote)
git push <remote> <branch>
# 重命名遠端分支名(Rename a branch on remote)
git push <remote> : <old name>
git push <remote> <new name>
# 追蹤一個遠端庫(Track a remote repository)
git remote add --track <remote-branch><remote><url>
# 同步標籤到遠端庫(Publish your tags)
git push --tags
抓取 / 切換 Repository 的 branch
git fetch origin
# 擷取所有遠端儲存庫
git fetch
# 擷取遠端儲存庫的 branch_name 分支
git fetch <branch_name>
# 從遠端庫更新所有的訊息到本地,但是不合並,並清除已刪除的遠端分支。
(Download all changes fromm remote,but don't merge in HEAD and clean up deleted branchs from origin)
git fetch -p <remote>
# 抓取 reps-branch, 並將此 branch 建立於 local 的 reps-branch
git checkout --track -b reps-branch origin/reps-branch
刪除 Repository 的 branch
git push origin :heads/reps-branch
子模組
# 新增子模組
git submodule add <url>
# 初始化子模組
git submodule init
# 更新子模組
git submodule update
Reference:http://wiki.yobi.be/wiki/Git
Reference:http://josephj.com/entry.php?id=308
Reference:https://blog.miniasp.com/post/2013/08/18/Learning-Git-Part-1-Installation-Options-Tool-Usage-on-Local.aspx
Reference:https://www.jianshu.com/p/97946d9df5bd
Reference:https://tedsieblog.wordpress.com/2017/01/19/basic-git-commands/
Reference:https://blog.csdn.net/wangeen/article/details/27319699
Reference:https://zhaopeng0103.github.io/%E5%B7%A5%E5%85%B7/Git%E5%9F%BA%E6%9C%AC%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/