banner
lMingyul

lMingyul

记录穿过自己的万物
jike

常用系列-Git命令

常用系列就是記錄自己編程常用的東西,此文為常用系列第 2 篇,用於記錄自己日常常用的 Git 命令,以便需要時查找。Git 儘管提供了 GUI 界面進行操作,但是我覺得 Git 的 GUI 軟體有很多,但是掌握最常用的命令還是一個合格的程序員應該做的,畢竟命令到哪裡都一樣,但 GUI 軟體萬一哪一天用不了了呢🐶,而且命令行模式可以執行 Git 的所有命令

Git 最基本的操作#

文件從本地到倉庫流程:以下記錄一下用哪些命令可以將一個文件從自己的本地推送到遠端的倉庫,我把這稱為基本操作

安裝 Git#

如果想要在 Mac 電腦安裝 Git,只需要輸入查詢 git 版本的命令就會提示你安裝(如果你之前沒裝過的話)

git --version

配置用戶信息#

安裝完 git 之後對 git 的環境進行配置,這些配置在每台計算機只需要配置一次,當然配置完以後也可以修改,git 最常用的配置就是對用戶名和郵箱地址的設置,--global代表對系統上所有倉庫都生效。

# 設置用戶簽名,可在 .gitconfig 文件中查看
git config --global user.name <用戶>

# 設置用戶郵箱,可在 .gitconfig 文件中查看
git config --global user.email <註冊git倉庫郵>   

Config 有三個作用域:當不明確設置是默認為 local

  • local:只對某個倉庫有效
  • system:對系統所有登錄的用戶有效

顯示 config 的配置#

git config --list --local

git config --list --global

git config --list --system

獲取 Git 倉庫#

通常獲取倉庫有兩種方式:

  • 將本地目錄轉換為 Git 倉庫
  • 從別的地方複製一個倉庫到你的本地

在已存在目錄中初始化倉庫#

git init

這個命令會在當前目錄下創建一個.git的目錄,目錄中包括初始化倉庫的所有文件

克隆倉庫#

git clone https://github.com/libgit2/libgit2

這個命令會從遠端 GitHub 的 libgit2 倉庫拉取所有東西到你當前目錄

記錄文件狀態#

文件的狀態有 2 種:已被跟蹤、未被跟蹤,跟蹤的意思是現在 git 可以記錄這個文件發生的所有變化(被修改、被刪除、重命名)

查詢文件狀態#

git status

# 簡潔輸出文件狀態,A-先添加到暫存區、M-修改過的文件、D-刪掉的文件、R-重命名的文件、??-未被跟蹤的文件
git status -s

跟蹤新文件#

# 使用以下命令之後,一般都會再使用 git status 查看文件是否被跟蹤
git add <文件>

# 將所有待加入暫存區的文件加入暫存區
git add . / git add -A

# 將已經被 git 追蹤的文件的變更加入到暫存區(不包括未被追蹤的文件,即新文件)
git add -u

使用該命令之後,文件就會被放入 git 的暫存區,暫存區裡面的文件都是即將要推送到遠端倉庫的候選者。

對比區別#

對比已暫存的文件與未暫存文件之間的區別

通常我們修改文件過多時就會容易忘記某個文件修改過的內容,這個時候就需要查看我們做過哪些修改就可以使用diff命令

# 文件需在暫存區,即被跟蹤才能使用本命令
git diff <文件>

# 如果不加文件名,則比較的是工作區與暫存區之間的區別
git diff

如果你想對比暫存區裡的文件與上次提交時文件的區別,就可以使用以下命令

git diff --cached

也可以對比兩次不同 commit 之間的區別

git diff <Commit id0> <Commit id1>

# 如果是對比兩個 commit 之間某個文件的區別,則加上 -- 
git diff <Commit id0> <Commit id1> -- [文件名]

給文件和文件夾重命名#

git mv 是 Git 中用來重命名或移動文件或文件夾的命令

# 這個命令會將文件從舊路徑移動到新路徑,並且將這個更改加入到 Git 的暫存區
git mv <old-filename> <new-filename>

提交更新#

如果你的暫存區裡面已經包括你本次想要提交的文件,就可以通過commit命令對文件的修改進行提交

# 每次commit都會清空暫存區
git commit -m "<雙引號裡面填的是本次提交文件的一個描述信息>"

推送文件到遠端#

添加遠端倉庫#

如果你不是從遠端倉庫克隆 clone 的文件,而是自己在本地自己創建的 git 倉庫,就需要在向遠端倉庫推送之前加上你要推送的倉庫

git remote add https://github.com/paulboone/ticgit

推送#

git push origin master

這個命令代表著將 master 分支的代碼推送到遠端的 origin 伺服器

到此一個文件從創建到最終同步到遠端倉庫的這個過程就圓滿完成。

下面就記錄一下在使用 git 的過程中遇到一些情況該使用哪些命令。

提交操作#

修改上一次(最近一次) Commit#

  • 修改上次 commit 填的信息
  • 基於上次的 commit 再次添加修改或者添加文件

以上的情況都可以使用以下這個命令

# 這個命令是基於上次的 commit 的,不會生成新的 commit
git commit --amend

查詢#

這裡的記錄是使用 git 場景下各種需要查的情況

查提交歷史#

整個項目歷史提交記錄#

git log

commit ca82a6dff817ec66f44342007202690a93763949 
Author: Scott Chacon <[email protected]m> 
Date: Mon Mar 17 21:52:11 2008 -0700

			changed the version number

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 
Author: Scott Chacon <[email protected]m> 
Date: Sat Mar 15 16:40:33 2008 -0700

			removed unnecessary test

# 以一行的形式展示過往所有的提交
git log --pretty=oneline

# 分支提交圖
git log --graph
git log --graph --pretty=oneline --abbrev-commit

# 僅查看最近K次的提交
git log -n K

輸出的內容依次是:

  • 每個提交的 SHA-1 校驗和
  • 提交人的名字
  • 郵箱地址
  • 提交時間
  • 提交說明

文件的歷史提交記錄#

查看單個文件每次的提交記錄

git log -p <文件>

# 只顯示最近 2 次提交
git log -p -2 <文件>

每一行的提交記錄#

能顯示任何文件中每行最後一次修改的提交記錄

git blame <文件>

# 限定顯示哪一行
git blame -L 69,82 <文件>

查找 BUG#

很多時候,當前分支出現問題了,但不清楚哪裡出現了問題,就可以使用git bisect命令查找哪一次代碼提交引入了錯誤

這個命令使用的原理是二分查找的原理:

通過二分【代碼是沒問題的提交 ~ 當前有問題的分支】這個範圍找到可能有問題的那一次提交

git bisect start命令啟動查錯,它的格式如下:

$ git bisect start [終點] [起點]

終點是最近的提交,起點是更久以前的提交。它們之間的這段歷史,就是差錯的範圍

當不清楚哪個起點提交時沒問題的時候可以選擇最開始的分支

# 終點是當期分支 HEAD,起點是第一次提交 4d83cf
git bisect start HEAD 4d83cf

執行上面的命令以後,當前的代碼就會切換到這段範圍當中中間的那一次提交

然後你就可以對當前代碼進行測試,如果是沒有問題就執行以下命令對本次提交進行標識

git bisect good

如果沒問題就意味著錯誤是在代碼歷史的後半段引入的。執行上面的命令,Git 就自動切換到後半段的中點

然後再進行測試,如果是有問題的就標識這個提交是有問題的

git bisect bad

到這裡不是就結束了哦,有問題只是這次有問題,但我們需要找到第一次有問題的提交

接下來,不斷重複這個過程,直到成功找到出問題的那一次提交為止。這時,Git 會給出如下的提示。

b47892 is the first bad commit

然後就可以去分析這次都提交了哪些文件,從而分析錯誤是什麼原因引起的

注意:代碼缺陷需要自己去判斷的,git 是沒辦法幫你分析出哪裡有問題

然後,使用git bisect reset命令,退出查錯,回到最近一次的代碼提交。

查找內容#

由於 git 與 Linux 命令一樣,同樣可以與 grep搭配使用

git grep -n ""

撤銷#

我們在操作 Git 的時候難免會出現出錯的時候,修改錯誤的辦法一般不是重新修改就是回退到沒問題的時候

文件的撤銷#

工作區的操作#

  1. 將文件尚未加入暫存區的修改全部撤銷
# -- 很重要,沒有--,就變成了“切換到另一個分支”的命令 
git checkout -- <文件> 

# 恢復暫存區的所有文件到工作區
git checkout .

# 恢復 commit 的指定文件到暫存區和工作區
git checkout [commit] [file]
  1. 將工作區相對於暫存區的修改撤銷,如果暫存區沒有對應的文件則回退到 HEAD 指向的版本
git restore <文件>

暫存區的操作#

  1. 將暫存區的文件修改撤銷掉(unstage),重新放回工作區
git reset HEAD <文件>

# 如果不加文件名,則是將暫存區的所有文件都重新放回工作區
git reset HEAD

版本的撤銷#

常用於提交版本之後,遠端發生衝突無法 merge 分支,用git resrt回退版本處理完衝突後再進行推送

# 將commit過的代碼庫回滾到上個版本
git reset --hard HEAD^ git reset --hard HEAD~   

# 往上回滾兩次版本,以此類推
git reset --hard HEAD^^:

# 往上回滾100個版本
git reset --hard HEAD~100:

# 回滾到某一特定版本,版本號為前7位,使用git reflog可以查出
git reset --hard 版本號:

堆棧操作#

平時開發的時候會經常出現一個需求開發到一定程度,本地代碼已經修改很多了,但是突然有一個臨時的 BUG 需要緊急處理,這個時候已經修改過的代碼就可以通過放進 git 的堆棧中進行保存,等 BUG 處理完之後再恢復現場繼續需求的開發

# 將本地的修改保存到堆棧中
git stash

# 查看堆棧中的情況
git stash list

# 將堆棧中的最頂部的修改恢復,不會將堆棧的信息刪除掉
git stash apply

# 將堆棧中的最頂部的修改恢復,同時會將堆棧的信息刪除掉
git stash pop

分支操作#

分支基本操作#

# 列出所有本地分支,當前分支前面會標一個*號
$ git branch

# 列出所有遠程分支
$ git branch -r

# 列出所有本地分支和遠程分支,並詳細展示分支信息
$ git branch -av

# 新建一個分支,並切換到該分支
$ git checkout -b [branch]

# 切換到指定分支,並更新工作區
$ git checkout [branch-name]

# 切換到上個分支
$ git checkout -

# 刪除分支,刪除的前提是要刪除的這個分支的修改已經合併到上游分支,否則會刪除失敗
$ git branch -d [branch-name]

# 強制刪除分支,無視警告
$ git branch -D [branch-name]

merge#

用於合併兩個分支

# 合併指定分支到當前分支
$ git merge [branch]

rebase#

也用於分支合併

合併分支的操作與 merge 基本一樣,

# 合併指定分支到當前分支
git rebase [branch]

如果 git rebase 遇到衝突:

  1. 第一步手動解決衝突,然後把新修改的文件加入暫存區 git add .
  2. 之後並不需要 git commit,而是直接運行git rebase --continue

至於git mergegit rebase有什麼區別呢?

  • git merge合併完之後會顯示出來合併之前的分支,而git rebase合併之後看起來並不會有之前合併的分支記錄
  • 分支合併的順序也不一樣

詳細可以看一下這個博客 git merge 和 git rebase 小結

cherry-pick#

合併指定提交到當前分支

# 選擇一個 commit,合併進當前分支
git cherry-pick [commit]

# 合併多次提交到當前分支
git cherry-pick <HashA> <HashB>

# 合併連續一段的提交,A 提交必須早於 B,提交 A 不會包含本次提交
git cherry-pick A..B 

# 合併連續一段的提交,A 提交必須早於 B,本次提交包含提交 A
git cherry-pick A^..B 

如果 cherry-pick過程中發生衝突,則在手動處理完衝突之後使用--continue命令讓過程繼續

  1. 解決代碼衝突後,將修改的文件重新加入暫存區git add .
  2. 使用下面的命令,讓 Cherry pick 過程繼續執行。
 git cherry-pick --continue

參考資料#

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。