Git 常用命令彙總(99%的工作場景看這篇就夠了)

分支的三個版本

  • 遠程版本庫,如 github.com;
  • 遠程快照,使用 git branch -r 查看到的 origin/branch-name,相關信息在 .git/refs/remotes 中;
  • 本地分支,使用 git branch 查看到的分支,相關信息在 .git/refs/heads 中。一般本地分支會關聯到對應的遠程分支;

倉庫與版本庫

可理解爲:倉庫 = 版本庫 + 工作區。版本庫即 .git 文件夾內容,版本庫以外的都是工作區內容。

工作區、暫存區、版本區

  • 工作區:即我們能看到的目錄和文件(除了 .git 這個隱藏目錄),對代碼的修改發生在工作區;
  • 暫存區:使用 git add . 將工作區的修改轉移到暫存區。暫存區是工作區和版本庫(分支)的中轉站;
  • 版本庫:使用 git commit -m 將暫存區的內容轉移到版本庫中,並生成提交記錄;

.git 目錄概覽

  • 幾個 HEAD
    • FETCH_HEADgit fetch 用到的,記錄了遠程倉庫每個分支的 HEAD 指向;
    • HEAD:本地倉庫所在的版本;
    • ORIG_HEAD:針對一些危險操作(如 git reset --hard),git 記錄了上次 HEAD 的值以防回退(如可以執行 git reset --hard ORIG_HEAD 回退剛剛執行的 reset 操作);
  • config:配置信息;
  • hooks/:鉤子 shell 腳本;
  • logs/:操作日誌;
  • objects/:git 對象;
  • refs:引用;

本地倉庫與遠程倉庫

  • git 是分佈式版本管理系統,大體上分爲本地倉庫遠程倉庫。一個本地倉庫可以關聯 0 個或多個遠程倉庫。最常用的遠程倉庫默認命名爲 origin。
  • 創建倉庫的幾種方式:
    • 基於遠程倉庫創建本地倉庫(clone):git clone [email protected]:linvanda/cache2go.git
    • 在本地創建一個空的倉庫:mkdir proj & cd proj & git init;(git init 與 git init --bare 的區別:git init --bare 生成的是裸版本庫,不帶工作區,相當於 git init 生成的 .git 內容);
  • 本地倉庫與遠程倉庫的關聯:
    1. 創建本地倉庫:mkdir proj & cd proj & git init
    2. 添加遠程倉庫關聯:git remote add origin [email protected]:linvanda/cache2go.git
    3. 可以添加多個遠程倉庫關聯,再加一個:git remote add other [email protected]:linvanda/cache2go-other.git,操作時可指定倉庫,如 git push other 將推送到 other 倉庫;
  • 遠程倉庫源的一些操作:
    • 查看遠程源列表:git remote -v
    • 添加遠程源: git remote add origin [email protected]:linvanda/cache2go.git
    • 移除遠程源:git remote remove origin
    • 重命名遠程源:git remote rename origin new-origin

基於遠程倉庫的分支創建本地分支

  1. git fetch:將 遠程倉庫分支 fetch 到本地的遠程倉庫快照中;
  2. git checkout branch-name:自動基於 origin/branch-name 快照創建本地分支並切換到該分支;

基於 master 創建本地分支並推送到遠程倉庫

  1. git checkout master:切換到 master 分支;
  2. git pull --rebase :更新 master 分支到最新版本;
  3. git checkout -b branch-name:基於 master 創建開發分支;
  4. git add . & git commit -m "commit reason",開發並提交修改;
  5. git push -u origin branch-name:將該分支推送到遠程並在兩者之間創建關聯(這樣後面就可以直接執行 git push 推送分支);

git pull 的兩種模式:rebase 和 merge

  • merge 模式:直接執行 git pull 默認就是該模式。該模式是將遠程分支 fetch 下來,然後將其 merge 到相應的本地分支,並在 log 中生成一條 commit。使用該模式下,git log 查看 commit 會發現大量的 merge origin/branch-name into branch-name 的無意義的合併日誌。
  • rebase 模式:git pull --rebase。推薦使用的模式。將遠程分支 fetch 下來後,將其 rebase 到本地分支,相當於“追加”,不會生成 commit。

合併分支

合併分支的最佳實踐(以將 feature-order 開發分支合併到 test 測試分支爲例):

  1. git checkout feature-order,進入 feature-order 分支;
  2. git pull --rebase,同步當前分支到最新版本;
  3. git checkout test,進入 test 分支;
  4. git pull --rebase,同步 test 分支到最新版本;
  5. git merge --no-ff feature-order,將 feature-order 合併到 test 分支;
  6. git push,推到遠程;

注:

  • 爲啥加 --no-ff:no ff 是 no fast forward 的縮寫。git merge 默認是fast forward(快進) 模式,該模式下可能不會生成單獨的 commit,這對歷史查看和回滾都不便。加 --no-ff 則強制生成獨立的合併 commit;
  • 出現衝突咋辦?出現衝突時一定要找衝突相關人一起解決,解決完畢後執行 git add . & git commit 即可。如果無法解決衝突,則要撤銷此次合併:git merge --abort

git diff

  • git diff A B B相對於A有什麼不同。如果不指定B,則B默認是工作區;如果同時不指定A,則A默認是暫存區。
  • git diff 相當於 git diff stage workspace 。 工作區相對於暫存區 有哪些不同。
  • git diff HEAD 相當於 git diff HEAD workspace 。 工作區相對於HEAD區 有哪些不同。
  • git diff commitId 相當於 git diff commitId workspace。 工作區相對於commitId那次提交 有哪些不同。
  • git diff commitIdA commitIdB commitIdB相對於commitIdA有哪些不同
  • git diff master 相當於 git diff master workspace: 當前工作區相對於master分支的最近提交有哪些不同。
  • git diff master HEAD 當前的HEAD相對於master分支最近提交有哪些不同
  • git show commitID 本次提交相對於上次提交有何不同

撤銷修改

  • 撤銷 workspace 中某個文件的修改:git checkout < filename >
    變體:git checkout:撤銷工作區所有文件的修改。
  • 撤銷 stage 中某個文件的修改(將其放入 workspace):
    git reset HEAD <filename>
    變體:git reset HEAD 撤銷暫存區所有文件修改到工作區
  • git reset --hard HEAD 撤銷修改並丟棄(不放回工作區), 此時工作區內容和HEAD中的相同。

合併 commit

有時我們在本地開發時會經常地 commit,但又不想將這些瑣碎的 commit 提交到遠程倉庫,則可以將它們合併提交。合併本地多次 commit 爲一條 commit:
1. git rebase -i HEAD~4
2. 彈出文本,將第二行開始的pick改爲s(或squash)
3. 保存,退出
4. 推到遠程:git push -f

對比文件修改歷史

查看某個文件每行的修改歷史,一般在需要對某個文件做詳細變化追蹤時用到:
git blame filename

歷史日誌 log

  • git log --grep="test" 搜索提交信息中包含 test 的
  • git log -S abc 搜索修改內容包含"abc"的 commit
  • git log --date=relative 以相對日期格式顯示日誌(如2 hours ago)
  • git log —oneline 一行緊湊顯示提交id和註釋
  • git log --abbrev-commit 顯示短 commit id
  • git log -5 顯示最近5條提交
  • git log —all 顯示所有分支的提交歷史(默認只顯示當前分支的)
  • git log —graph 圖形顯示分支
  • git log --pretty=format:'…' 格式化顯示

格式化顯示日誌

git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
可設置別名:
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”

刪除 untracked files

刪除未跟蹤(未納入到版本管理)的文件:

  • 刪除文件:git clean -f
  • 連 untracked 的目錄也一起刪掉: git clean -fd

cherry-pick

將一個分支的某個 commit 的改動應用到另一個分支。
如在分支 A 做了些修改並提交後,想把這些修改應用到分支 B,但又不能直接 merge A 到 B,又不想手動 copy,此時可以用 cherry-pick:

  1. 切換到分支 B:git checkout B
  2. 將 A 的某個 commit 應用到 B:git cherry-pick commitid-from-A

撤銷合併

  1. 查看合併提交詳情:git show mergecommitid,會有如下一行:Merge: 022ff6f b2cd947,其中022ff6f和 b2cd947分別是兩個分支合併前最近提交的commitId。
  2. 撤銷合併時用-m指定需要以誰爲準(主幹mainline):
    git revert -m 1 mergecommitid,這樣就回退到 022ff6f身上(丟棄掉被合併分支的一系列提交)。
  3. 撤銷合併前用 git log —graph 能很清晰的看出分支合併關係以及將要撤銷掉的提交系列。
  4. 一般情況下,我們都是錯誤合併後需要撤銷到合併之前的狀態,因而一般都是 git revert -m 1 …

刪除本地分支

git branch -D branch-name

刪除遠程分支

git push origin :branch_name

git push --delete origin branch_name

基於已有分支創建新分支

  • git checkout -b branch_a origin/branch_a: 創建本地分支 branch_a 並追蹤到遠程分支 origin/branch_a;
  • git checkout -b branch_a:基於當前分支(如master)創建新分支 branch_a, 不會追蹤任何遠程分支,此時要用 git push -u origin branch_a:branch_a 追蹤並推送到遠程倉庫。

提交

git commit -am '…'
-a:add 將未暫存的文件也提交(注意此方式不適用新創建的文件,新建的文件仍然要 git add .)。

git flow

一種不錯的分支管理策略,我們公司就是基於 git flow 設計的分支管理策略。
介紹
安裝: apt-get install git-flow

批量刪除分支

實際開發過程中,長時間不清理分支後,存在大量的開發分支,造成分支查找困難,我們需要不定期清理不需要的分支。

  • 批量刪除本地分支:git branch |grep release|xargs git branch -D (刪除本地release分支)
  • 批量刪除遠程分支:git branch -r|awk -F '[/]' '/release/ {printf "%s\n", $2}'|xargs -I {} git push --delete origin {} (刪除遠程release分支)

從倉庫中刪除已跟蹤的文件(將文件變成untracked,不跟蹤)

有時候把 vendor、IDE 配置文件(如 .vscode 等)誤加到版本控制裏面了,需要移除掉。

  • git rm --cached $file_name
  • git rm --cached -r $dir_name

刪除遠程不存在的“本地遠程分支“

很多時候其他人刪除了遠程分支,但我們自己電腦上還有一大堆 origin/… 這些“本地遠程分支”,可執行以下指令同步刪除:
git remote prune origin 或者git pull -p

同時推送到多個源

比如我們自己開發了一個代碼庫,想同時推送到公司 gitlab 和自己的 github 倉庫。
添加新的源:git remote set-url --add --push origin https://github.com/linvanda/wecarswoole.git
這樣 git push 的時候就會 push 到多個源。

換行符問題(mac、windows、linux混合開發時可能遇到)

有幾種配置策略:

  • git config --global core.autocrlf true (提交時自動將CRLF轉成LF,檢出時將LF轉成CRLF)
  • git config --global core.autocrlf input (提交時自動將CRLF轉成LF,檢出時不處理(意味着檢出時是LF))
    (以上兩個都是保證git倉庫中是LF)
  • git config --global core.autocrlf false (關閉,不處理,是啥就是啥)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章