Git常用命令總結

1 Git 簡介

Git 是一個開源的分布式版本控制系統,最初由 Linus Torvalds 為管理 Linux 內核而開發的開源軟件,目前已應用在 Windows、Linux、MacOS 等操作系統上。

SVN 也是一種版本控制系統,但是其采用集中式管理方式,容易出現單點故障,容錯性差。Git 采用分布式管理方式,沒有中央服務器,每個人的電腦都是一個完整的版本庫。

Git 常用命令流程圖如下:

Git下載地址見→Git - Downloads

2 Git 配置

2.1 配置用戶信息

1)查看用戶信息

git config --global -l --show-origin
git config user.name
git config user.email
git config user.password

2)修改用戶信息

git config --global user.name "xxx"
git config --global user.email "xxx@qq.com"
git config --global user.password "xxx"

2.2 配置 ssh key

使用 SSH 拉取代碼時,需要配置 ssh key。

1)生成 ssh 密鑰對

# 創建 ssh key(可以省略 -C 屬性, rsa密鑰長度建議至少2048位, 默認1024位不安全, 可能導致SSH密鑰無法正常工作, gitcode服務器要求至少2048位)
ssh-keygen -o -t rsa -b 4096 -C "email@example.com"

說明:運行 ssh-keygen 命令后,將在本地用戶目錄下的 .ssh 目錄下(如 C:\Users\81518.ssh\ ),生成 id_rsa(私鑰)和 id_rsa.pub(公鑰),公鑰需要配置在服務器上。公鑰和私鑰的作用如下:

  • 在數據傳輸時,公鑰用于加密,私鑰用于解密。
  • 在身份認證時,私鑰用于簽名,公鑰用于驗證。

2)查看公鑰

cat ~/.ssh/id_rsa.pub

3)配置公鑰

登錄 gitcode、github 等官網,點擊用戶頭像,依次選擇 settings→SSH keys→New SSH key,將公鑰粘貼并保存,如下。

4)測試 ssh 連通狀態

# 測試SSH密鑰是否能夠正常工作
ssh -T git@gitcode.net
ssh -T git@github.com

2.3 配置代理

1)查看代理

# 查看代理
git config http.proxy
git config https.proxy

2)設置 http 拉代碼的代理

如果通過 http 拉代碼,可以設置代理如下。

# 設置代理
# http/https代理
git config --global https.proxy http://127.0.0.1:1080
git config --global https.proxy https://127.0.0.1:1080
# socks5代理(ss、ssr)
git config --global http.proxy socks5://127.0.0.1:1080
git config --global https.proxy socks5://127.0.0.1:1080

# 只對github使用代理, 其他倉庫不走代理
# http/https代理
git config --global http.https://github.com.proxy http://127.0.0.1:1080
git config --global https.https://github.com.proxy https://127.0.0.1:1080
# socks5代理(ss、ssr)
git config --global http.https://github.com.proxy socks5://127.0.0.1:1080
git config --global https.https://github.com.proxy socks5://127.0.0.1:1080

3)取消代理

# 取消全局代理
git config --global --unset http.proxy
git config --global --unset https.proxy

# 取消github代理
git config --global --unset http.https://github.com.proxy
git config --global --unset https.https://github.com.proxy

4)設置 ssh 拉代碼的代理

如果使用 git@ 拉代碼,在 ~/.ssh/config 文件(沒有可以新建一個)里添加以下內容。

Host github.com
User git
ProxyCommand connect -H 127.0.0.1:1080 %h %p

Host github.com
User git
ProxyCommand connect -S 127.0.0.1:1080 %h %p

2.4 其他配置

1)免密拉取代碼或推送代碼

執行以下命令后, 再拉代碼或推送代碼, 需要輸一次密碼, 以后就不需要輸入了。

git config --global credential.helper store

2)綁定遠程分支

git branch --set-upstream-to=origin/branch_name
# 如: git branch --set-upstream-to=origin/master
# 綁定后, 就可以通過git pull拉代碼, 通過git push推送代碼
# 而不必使用git pull origin master拉代碼, 不必使用git push origin master推送代碼

3 拉取代碼

3.1 首次拉取代碼

1)克隆代碼

# 下載一個項目和它的整個代碼歷史
git clone [repository_url]
# 下載一個項目和它的整個代碼歷史, 并將項目根目錄重命名為repository_name
git clone [repository_url] [repository_name]
# 下載指定分支的代碼
git clone -b [branch_name] [repository_url]
# 下載項目及其所有依賴子模塊(遞歸拉取)
git clone --recurse-submodules [repository_url]

2)拉取依賴模塊

# 如果執行clone時忘記了添加--recurse-submodules, 進入項目根目錄后, 執行以下命令可以繼續拉所有依賴子模塊(遞歸拉取)
git submodule update --init --recursive

3.2 非首次拉取代碼

1)查看工作區是否有改動

# 同步代碼前, 執行以下命令, 如果打印: Your branch is up to date, 說明本地沒有修改, 同步代碼不會有沖突, 可以放心拉代碼了
git status

2) 拉取代碼

# 下載遠程倉庫的所有變動
git fetch [remote]

# 取回遠程倉庫的變化,并與本地分支合并
git pull [remote] [branch]

4 提交代碼

4.1 首次提交代碼

此處“首次”是指遠程倉庫剛創建之后提交的第一筆代碼。用戶如果想將某個目錄里面的文件提交到遠程倉庫,cd 到該目錄下,再執行以下流程。

1)初始化本地倉庫

git init

2)將本地倉庫與遠程倉庫關聯

git remote add origin [repository_url]

3)提交代碼

# 將當前目錄的所有文件添加到暫存區
git add .
# 提交暫存區所有文件到本地倉庫
git commit -m [message]
# 將本地的master分支推送到origin主機, 同時指定origin為默認主機, 后面就可以不加任何參數使用git push了
git push -u origin master

4.2 非首次提交代碼

1)查看工作區改動了哪些文件

# 提交代碼前, 執行以下命令, 查看修改了哪些文件(不顯示具體改動的內容, 只顯示改動的文件名)
git status

2)查看工作區改動的內容

# 顯示暫存區和工作區的差異(所有文件)
git diff

# 顯示暫存區和工作區的差異(指定文件)
git diff [file]

3)工作區 → 暫存區

# 添加指定文件到暫存區
git add [file1] [file2] ...
# 將指定目錄添加到暫存區
git add [dir]
# 將當前目錄的所有文件添加到暫存區
git add .

4)暫存區 → 本地倉庫

# 提交暫存區指定文件到本地倉庫
git commit [file1] [file2] ... -m [message]
# 提交暫存區所有文件到本地倉庫
git commit -m [message]

說明:message 為提交的日志說明。

5)本地倉庫 → 遠程倉庫

# 上傳本地指定分支到遠程倉庫
git push [remote] [branch]

# 強行推送當前分支到遠程倉庫,即使有沖突
git push [remote] --force

# 推送所有分支到遠程倉庫
git push [remote] --all

6)合并遠程倉庫代碼

# 合并指定分支到當前分支
git merge [branch_name] --no-ff

說明:--no-ff 表示不使用“快進合并”(fast-forward merge),快進合并會直接將目標分支的更改合并到當前分支,而不創建新的合并提交。使用 --no-ff 選項會強制創建一個新的合并提交,這樣可以保留更清晰的合并歷史,更容易追溯分支的合并情況。

5 導出、導入 patch

patch 是 commit 的離線數據,用戶 A 可以導出 patch 發給用戶 B,用戶 B 導入 patch 就可以同步用戶 A 的本地代碼。

5.1 導出 patch

# 導出最近的 1 個提交, 生成 0001-Update.patch 文件
git format-patch -1
# 導出最近的 2 個提交, 生成 0001-Update.patch、0002-Update.patch 文件
git format-patch -2
# 導出最近的 1 個提交, 生成 xxx/0001-Update.patch 文件
git format-patch -1 -o xxx

說明:用戶 A 在執行 git format-patch 前,需要執行 git commit 將數據提交到本地倉庫(不要執行 git push 提交到遠程倉庫)。

5.2 導入 patch

# 導入 0001-Update.patch 差異數據
git am 0001-Update.patch
# 導入所有差異數據
git am *.patch
# 應用 patch 時沖突了, 解決沖突后, 使用以下命令繼續應用 patch
git am --continue

6 解決沖突

1)工作區 ? 臨時空間

# 將工作區改動代碼提至臨時空間, 同時將暫存區的代碼同步至工作區(清除本地修改)
git stash
# 拉取代碼之后, 執行下述命令, 將臨時空間的代碼同步至本地
git stash pop  
# git stash apply

2)撤銷 modify(只改變工作區)

# 清除工作區中未暫存的修改(指定文件)
git checkout [file1] [file2] ...
# 清除工作區中未暫存的修改(所有文件)
git checkout .

# 清除工作區中未暫存的修改(指定文件, Git 2.23 版本新引入)
git restore [file1] [file2] ...
# 清除工作區中未暫存的修改(所有文件, Git 2.23 版本新引入)
git restore .

3)撤銷 add(只改變暫存區)

# 撤銷 add 的指定文件 (不改變工作區, Git 2.23 版本新引入)
git restore [file1] [file2] ... --staged

# 撤銷 add 的所有文件 (不改變工作區, Git 2.23 版本新引入)
git restore . --staged

4)撤銷 add 和 modify(改變暫存區和工作區)

# 撤銷 add 和 modify (不能指定文件, 會撤銷所有修改)
git reset --hard

5)撤銷 commit(只改變本地倉庫)

# 撤銷 commit (只改變本地倉庫, 不改變暫存區, Git 2.23 版本新引入)
git reset HEAD^ --soft

6)恢復歷史版本

方法一:

# 后退 n 步,每步都后退到第 1 個提交上
git reset HEAD~n

# 后退 1 步,這步后退到第 n 個提交上
git reset HEAD^n

說明: 當省略 n 時,相當于 n 為 1,如:git reset HEAD~ 等效于 git reset HEAD~1,git reset HEAD^ 等效于 git reset HEAD^1

方法二:

# 查看歷史版本信息(可以得到 commitId)
git log [--oneline]

# 根據 commitId 回退至指定版本
git reset commitId

說明:reset 只會回退本地倉庫和暫存區的內容,不會回退工作區的內容,如果想回退工作區的內容,在 reset 命令的末尾加上 --hard;如果只想回退本地倉庫的內容,不回退暫存區的內容,在 reset 命令的末尾加上 --soft

7 檢視代碼

1)查看歷史版本信息

# 顯示當前分支的版本歷史(包含提交用戶、提交時間、commitId等信息)
git log [--oneline]

2)查看指定文件的修改情況

# 查看文件的相對路徑
find . -name "Test.java"

# 顯示指定文件是什么人在什么時間修改過
git blame [file]

8 分支管理

1)查看分支

# 列出所有本地分支
git branch
# 列出所有遠程分支
git branch -r
# 列出所有本地分支和遠程分支
git branch -a

2)新建分支

# 新建分支,但依然停留在當前分支
git branch [branch_name]

3)切換分支

# 新建一個分支,并切換到該分支
git checkout -b [branch_name]
# 創建一個名為local_master的新分支,并將其設置為跟蹤remotes/origin/master
git checkout -b local_master remotes/origin/master
# 切換到指定分支,并更新工作區
git checkout [branch_name]
# 切換到上一個分支
git checkout -

4)重命名分支

# 重命名分支
git branch -m <oldbranch> <newbranch>

5)刪除分支

# 刪除分支
git branch -d [branch_name]

9 統計代碼

1)統計所有開發者及其提交筆數

# -s: 顯示姓名, -e: 顯示郵箱, -n: 按提交數量排序
git shortlog -s -e -n

打印格式如下。

   220  little_fat_sheep <xxx@qq.com>
    15  zhyan8 <abc@qq.com>

2)統計用戶今天提交的代碼行數

git diff --author="little_fat_sheep" --shortstat "@{0 day ago}"

author 可以是用戶名,也可以是郵箱,刪除時,表示統計所有用戶的。打印格式如下。

28 files changed, 544 insertions(+), 143 deletions(-)

3)統計用戶近期提交代碼行數

# 用戶近1周提交代碼量
git log --author="little_fat_sheep" --since="1 week ago" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "添加行數: %s\n刪除行數: %s\n凈增行數: %s\n", add, subs, loc }'

# 用戶近半月提交代碼量
git log --author="little_fat_sheep" --since="15 day ago" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "添加行數: %s\n刪除行數: %s\n凈增行數: %s\n", add, subs, loc }'

# 用戶近1月提交代碼量
git log --author="little_fat_sheep" --since="1 month ago" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "添加行數: %s\n刪除行數: %s\n凈增行數: %s\n", add, subs, loc }'

# 用戶近1年提交代碼量
git log --author="little_fat_sheep" --since="1 year ago" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "添加行數: %s\n刪除行數: %s\n凈增行數: %s\n", add, subs, loc }'

author 可以是用戶名,也可以是郵箱,刪除時,表示統計所有用戶的。打印格式如下。

添加行數: 144943
刪除行數: 259107
凈增行數: -114164

4)統計用戶提交的代碼行數

git log --author="little_fat_sheep" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "添加行數: %s\n刪除行數: %s\n凈增行數: %s\n", add, subs, loc }'

author 可以是用戶名,也可以是郵箱,刪除時,表示統計所有用戶的。打印格式如下。

添加行數: 1443700
刪除行數: 883901
凈增行數: 559799

5)統計每個文件的行數以及總行數

git ls-files | xargs wc -l

打印格式如下。

       0 base/.gitignore
      48 base/build.gradle
       0 base/consumer-rules.pro
      10 base/proguard-rules.pro
       3 base/src/main/AndroidManifest.xml
...
   213152 total

6)統計各種語言的添加、刪除、凈增行數

git log --author="little_fat_sheep" --pretty=tformat: --numstat | awk '
    /\.java$/ { java_add += $1; java_sub += $2; java_net += $1 - $2 }
    /\.kt$/ { kotlin_add += $1; kotlin_sub += $2; kotlin_net += $1 - $2 }
    /\.js$|\.ts$/ { js_add += $1; js_sub += $2; js_net += $1 - $2 }
    /\.c$|\.h$/ { c_add += $1; c_sub += $2; c_net += $1 - $2 }
    /\.cpp$|\.hpp$|\.cc$|\.cxx$|\.hxx$/ { cpp_add += $1; cpp_sub += $2; cpp_net += $1 - $2 }
    /\.cs$/ { cs_add += $1; cs_sub += $2; cs_net += $1 - $2 }
    /\.m$|\.mm$/ { objc_add += $1; objc_sub += $2; objc_net += $1 - $2 }
    /\.swift$/ { swift_add += $1; swift_sub += $2; swift_net += $1 - $2 }
    /\.dart$/ { dart_add += $1; dart_sub += $2; dart_net += $1 - $2 }
    /\.py$/ { python_add += $1; python_sub += $2; python_net += $1 - $2 }
    /\.shader$|\.glsl$|\.vert$|\.frag$/ { shader_add += $1; shader_sub += $2; shader_net += $1 - $2 }
    /\.xml$/ { xml_add += $1; xml_sub += $2; xml_net += $1 - $2 }
    /\.json$/ { json_add += $1; json_sub += $2; json_net += $1 - $2 }
    /\.css$/ { css_add += $1; css_sub += $2; css_net += $1 - $2 }
    /\.html$|\.htm$/ { html_add += $1; html_sub += $2; html_net += $1 - $2 }
    /\.sh$|\.bash$|\.zsh$|\.bat$/ { shell_add += $1; shell_sub += $2; shell_net += $1 - $2 }
    END {
        print "代碼統計報告 - 作者: little_fat_sheep";
        print "=======================================================";
        print "語言類型      |    添加行數 |    刪除行數 |    凈增行數";
        print "-------------------------------------------------------";
        printf "%-13s | %11s | %11s | %11s\n", "Java", java_add, java_sub, java_net;
        printf "%-13s | %11s | %11s | %11s\n", "Kotlin", kotlin_add, kotlin_sub, kotlin_net;
        printf "%-13s | %11s | %11s | %11s\n", "JS/TS", js_add, js_sub, js_net;
        printf "%-13s | %11s | %11s | %11s\n", "C", c_add, c_sub, c_net;
        printf "%-13s | %11s | %11s | %11s\n", "C++", cpp_add, cpp_sub, cpp_net;
        printf "%-13s | %11s | %11s | %11s\n", "C#", cs_add, cs_sub, cs_net;
        printf "%-13s | %11s | %11s | %11s\n", "Objective-C", objc_add, objc_sub, objc_net;
        printf "%-13s | %11s | %11s | %11s\n", "Swift", swift_add, swift_sub, swift_net;
        printf "%-13s | %11s | %11s | %11s\n", "Dart", dart_add, dart_sub, dart_net;
        printf "%-13s | %11s | %11s | %11s\n", "Python", python_add, python_sub, python_net;
        printf "%-13s | %11s | %11s | %11s\n", "Shader", shader_add, shader_sub, shader_net;
        printf "%-13s | %11s | %11s | %11s\n", "XML", xml_add, xml_sub, xml_net;
        printf "%-13s | %11s | %11s | %11s\n", "JSON", json_add, json_sub, json_net;
        printf "%-13s | %11s | %11s | %11s\n", "CSS", css_add, css_sub, css_net;
        printf "%-13s | %11s | %11s | %11s\n", "HTML", html_add, html_sub, html_net;
        printf "%-13s | %11s | %11s | %11s\n", "Shell", shell_add, shell_sub, shell_net;
        print "=======================================================";
        printf "%-11s | %11s | %11s | %11s\n", "總計", 
            java_add + kotlin_add + js_add + c_add + cpp_add + cs_add + objc_add + swift_add + dart_add + python_add + shader_add + xml_add + json_add + css_add + html_add + shell_add,
            java_sub + kotlin_sub + js_sub + c_sub + cpp_sub + cs_sub + objc_sub + swift_sub + dart_sub + python_sub + shader_sub + xml_sub + json_sub + css_sub + html_sub + shell_sub,
            java_net + kotlin_net + js_net + c_net + cpp_net + cs_net + objc_net + swift_net + dart_net + python_net + shader_net + xml_net + json_net + css_net + html_net + shell_net;
    }'

author 可以是用戶名,也可以是郵箱,刪除時,表示統計所有用戶的。打印格式如下。

代碼統計報告 - 作者: little_fat_sheep
=======================================================
語言類型      |    添加行數 |    刪除行數 |    凈增行數
-------------------------------------------------------
Java          |       35809 |        8864 |       26945
Kotlin        |       24887 |        8216 |       16671
JS/TS         |             |             |
C             |         803 |           0 |         803
C++           |         791 |           0 |         791
C#            |        8160 |        2684 |        5476
Objective-C   |             |             |
Swift         |             |             |
Dart          |             |             |
Python        |             |             |
Shader        |        6797 |        3514 |        3283
XML           |        9520 |        3515 |        6005
JSON          |        8941 |        5067 |        3874
CSS           |             |             |
HTML          |             |             |
Shell         |         529 |          14 |         515
=======================================================
總計          |       96237 |       31874 |       64363

10 gitignore

在項目根目錄下配置 .gitignore 文件,可以忽略不需要更新的文件,如編譯構建的中間文件、日志文件、第三方依賴包的緩存等。

Android 項目的 .gitignore 文件如下。

*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

Unity 項目的 .gitignore 文件如下。

/Build
/Library
/Logs
/Temp
/UserSettings
/obj
/.idea
.vs
.vsconfig
Assembly-CSharp.csproj
Assembly-CSharp-Editor.csproj
Assembly-CSharp-firstpass.csproj

注意:.gitignore 文件需要在第一筆提交時提交上庫,否則忽略的文件可能會失效,如:先提交了 build 文件,再提交 .gitignore 文件,雖然 .gitignore 中配置了忽略 build,后面 build 中有變動也會被提交上庫的。當 .gitignore 中的文件(如 build)忽略失效時,可以先刪除對應文件(如 build)并提交上庫,之后再修改相關文件(如 build),就不會檢測到代碼更新。

11 Android Studio 中配置 Git

1)配置本地 git.exe

在【File】→【Settings】→【Version Control】→【Git】中選擇本地安裝的 Git,如下。

2)將本地項目導入到本地倉庫

在【VCS】→【Import Into Version Control】→【Create Git Repository】中,選擇當前項目的上級目錄。

3)將本地倉庫推送到遠程服務器

在【VCS】→【Git】→【Remote】中,輸入Name 和 URL,如下。

聲明:本文轉自Git常用命令總結

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容