天天看點

工作中如何使用 Git

開局一張圖

工作中如何使用 Git

大家好,我是沐華,可能大家或多或少的有遇到過類似圖檔這種情況,這是不是很煩,一個檔案還能這麼湊合,如果是多檔案,比如一個項目成千上萬個檔案,還可能多人修改,要是都這麼維護,就算不考慮占用存儲空間那也絕對是地獄級難度,是以 ​

​Git​

​ 出現了

本文将從 Git 入門到進階、由淺入深,從常用指令、分支管理、送出規範、vim 基本操作、進階指令、沖突預防、沖突處理等多方面展開,足以輕松應對工作中遇到的各種疑難雜症,如果覺得有所幫助,還望看官高擡貴手給個贊呗,感謝

雖說現在工作中使用 Git 都會用一些圖形化管理工具來提高開發效率。可事實上使用圖形管理化工具的前提,也是基于對指令都基本了解。還有比如我平時用的工具 ​

​GithubDesktop​

​ 因為不帶第三方合并工具,隻能手動解決沖突,而且有的功能沒有,隻能配合自己手動敲指令。

即使是工具也沒有那麼完美的工具,掌握指令才是​

​漁​

​​,工具隻是​

​魚​

​。其他的 Git 可視化管理工具比如:小烏龜、SourceTree、還有我們開發用的 IDE 內建的,本期就不過多介紹了

基本概念

Git 是一個開源的,也是目前最主流的分布式版本控制系統。

Git 的作用與好處是:

可以幫我們儲存檔案的所有修改記錄,并且使用版本号進行區分,讓我們随時可以浏覽曆史版本、對比不同版本的差異、還原到指定版本,起到恢複和保護作用的同時,還能和其他人同時修改,然後通過 Git 來合并修改的部分檔案,超級友善

不熟的同學别和 Github 搞混了,Git 是工具,Github 是平台,沒有什麼必然的聯系,就像 Java 和 JavaScript 也沒有什麼必然聯系一樣

Github 是一個主流的代碼托管平台。可以了解為存放和管理代碼的網盤,可以把自己的代碼傳上去進行共享和維護

安裝配置

安裝位址:​​Git - Downloads (git-scm.com)​​

安裝好後,指令行黑視窗是使用 ​

​Git Bash​

​​、​

​CMD​

​​、​

​Powershell​

​​、​

​終端​

​、或者編譯器内置的,這個就看個人喜歡了

接着可以再配置下預設使用者名和郵箱,比如配置全局的就用如下兩條指令,替換成自己的使用者名和郵箱,以後所有的項目都會預設這裡配置的使用者資訊

git config --global user.name 'xxxx'
git config --global user.email '[email protected]'      

如果隻需要在某個特定的項目中用其他的名字和郵箱,不用全局的,就把上面指令中的 ​

​--global​

​​ 去掉在項目下執行即可,或者不執行指令,直接在項目下的 ​

​.git/config​

​ 檔案裡添加如下,也可以

# xxx 指的是填你自己的使用者名和郵箱,不是真的寫 xxxx 上去
[user]
    name = xxxx
    email = [email protected]      

基本操作

先了解一下幾個基本概念:

  • 工作區:開發的地方,開發過程就是對工作區的操作
  • 暫存區:執行 ​

    ​git add xxx​

    ​ 指令後,會把目前修改過的檔案添加到暫存區
  • 本地倉庫:執行 ​

    ​git commit​

    ​ 指令完成後,會把目前暫存區的檔案放入本地倉庫
  • 遠端倉庫:就是用來托管代碼的伺服器(如:Github、Gitee、GitLab、工蜂、Bitbucket..),執行 ​

    ​git push​

    ​ 指令後,會把本地倉庫的檔案送出到遠端倉庫

常見選項

再認識一下幾個後面會用到多次的指令,之後就不一一解釋了

指令 縮寫 意思
--all -a 全部
--force -f 強制
--delete -d 删除
--delete --force -D 強制删除
--move -m 移動或重命名
--move --force -M 強制移動或重命名
-u 設定預設遠端分支

拉取遠端項目

拉取遠端項目到本地,先複制遠端項目連結,再在本地執行如下指令

# 拉項目
git clone https://xxxx
# 拉項目的同時自動初始化并更新項目中的每一個子子產品
git clone --recursive https://xxxx      

上傳本地項目

本地建立的項目,還沒有送出到遠端倉庫,就需要先關聯遠端倉庫。先在遠端建立一個空項目,并複制該項目的連結,然後在本地項目根目錄依次執行下面指令即可

git init                             // 初始化本地 Git 倉庫,會生成一個 .git 隐藏檔案夾
git remote add origin https://xxxx   // 将本地項目關聯遠端倉庫,後面的 https://xxxx 就是複制的遠端倉庫的連結
git pull --rebase origin master      // 上傳之前更新一下,確定沒有沖突,master 為分支名稱,--rebase 後面有介紹
git add .                            // 添加目錄下所有發生改變的檔案
git commit -m 'xxx'                  // 添加注釋資訊
git push -u origin master            // 送出到 master 分支      

其中 ​

​git remote add origin https://xxxx​

​​,就是往 ​

​.git/config​

​​ 檔案裡添加下面這一段,手動添加也可以,意思就是與遠端倉庫建立關聯。其他的幾條指令後面有介紹,我們先認識下 ​

​origin​

​ 為後面做鋪墊;

[remote "origin"]
  url = https://github.com/wmuhua/xxxx.git
  fetch = +refs/heads/*:refs/remotes/origin/*      

指令裡的 ​

​origin​

​​ 類似變量命名,這是預設的而已,沒什麼特别的意思,可以随便寫,假如改成 ​

​abc​

​​,後面的 ​

​git push origin xxx​

​​ 改成 ​

​git push abc xxx​

​ 即可,友善區分遠端倉庫的

由此可得出一個結論,就是一個項目可以關聯多個遠端倉庫,命不同的名就行了

沒錯

​git remote -v​

​ 可以快速檢視目前已經關聯的遠端倉庫清單

關聯多個遠端倉庫

可以使用 ​

​git remote add xxx​

​​ 添加多個,或者直接動在 ​

​.git/config​

​ 檔案裡添加。

比如一個項目同時關聯一個 ​

​Github​

​​ 倉庫和一個 ​

​Gitee​

​​ 倉庫,添加一個 ​

​remote​

​ 就是了,比如如下:

[remote "github"]
  url = https://github.com/wmuhua/xxxx.git
  fetch = +refs/heads/*:refs/remotes/github/*
[remote "gitee"]
  url = https://gitee.com/xxxx/xxxx.git
  fetch = +refs/heads/*:refs/remotes/gitee/*
[remote "all"]
  url = https://github.com/wmuhua/xxxx.git
  url = https://gitee.com/xxxx/xxxx.git
  fetch = +refs/heads/*:refs/remotes/all/*      

這樣當我們送出代碼的時候,想送出到 ​

​Github​

​​ 就用 ​

​git push github master​

​​,想同時送出到 ​

​Github​

​​ 和 ​

​Gitee​

​​ 的倉庫,隻需要 ​

​git push all master​

​ 即可

以指令的方法在某個 ​

​remote​

​​ 下添加 ​

​url​

​​ 如下,比如在上面 ​

​remote github​

​​ 下再添加一個 ​

​url​

​:

git remote set-url --add github https:/xxxx.git      

常用指令 add/commit/fetch/merge/pull/push

git add

# 添加一個檔案 test.js 到暫存區,多個檔案以空格隔開
git add test.js
# 添加全部檔案到暫存區
git add .      

git commit

# 會打開 vim 編輯器,vim 編輯器操作在下面展開說明
git commit
# 送出暫存區的檔案到本地倉庫,并備注目前 commit 記錄
git commit -m '備注資訊'
# 相當于 git add . 加上 git commit -m 'xxxx'
git commit -am 'xxxx'
# 用本地送出替換上次送出,比如不想保留上一次送出或者上一次送出描述資訊寫錯了之類的
git commit --amend      

git fetch

# 擷取 remote origin 對應遠端倉庫指定 master 分支的變更,但是不和本地的合并
git fetch origin master
# 意思一個樣,拉預設的分支而已
git fetch origin
# 也是,等效于 git fetch origin master:master,就是分支配置的預設值
git fetch
# 擷取預設遠端倉庫所有分支的變更
git fetch -a      

git merge

# 把本地的 test 分支分并到我目前分支
git merge test
# 合并 remote origin 對應遠端倉庫的 master 分支到目前分支
git merge origin/master
# --on-ff 是 no-fast-forward簡寫,合并并且會在分支上重新生成一個新的 commit 節點
git merge --on-ff origin/master
# 加入 --squash 表示合并,但是不生成 commit 記錄,通常用于把本地分支合入遠端分支
git merge test --squash
# 取消合并
git merge --abort      

git pull

​pull​

​​ 和 ​

​fetch​

​​ 都是下載下傳遠端分支,差別是 ​

​pull​

​​ 會和目前分支合并,​

​fetch​

​ 不會

# 拉取 remote origin 對應的遠端倉庫的 master 分支合并到本地的 test 分支
git pull origin master:test
# 這種同理就不解釋了
git pull origin
# git pull --merge 的簡寫,預設是 --merge 模式
# 等于 git fetch 加上 git merge,拉遠端預設分支到目前分支
git pull
# 把合并模式切換成 rebase,等于 git fetch 加上 git rebase,rebase 後面進階有介紹
git pull --rebase origin master      

git push

# 推送本地 test 分支到 remote origin 對應的遠端倉庫的 master 分支
git push origin test:master
# 上面同理,推送到遠端預設分支
git push origin test
# 縮寫,同理,用預設分支
git push origin
git push

# 相當于 git push origin master 加上 git branch --set-upstream master origin/master
# 推送并設定預設遠端分支
git push -u origin master
# 強制推送,就算本地和遠端有差異也推上去
git push -f origin master
# 删除遠端主機的 master 分支
git push origin -d master      

vim 基本操作

一點點小插曲

比如 ​

​git commit​

​​ 就會打開一個 ​

​vim​

​​ 的終端編輯器,讓我們寫送出說明,新手很容易在這個編輯器上面踩坑,不知道怎麼輸入,不知道怎麼退出,最後隻能關閉終端視窗,這也沒辦法,​

​vim​

​ 的操作确實有些反人類。

​vim​

​​ 打開預設是不能輸入的,要按 ​

​a​

​​ 或者 ​

​i​

​​ 進入編輯模式,輸入完成後,再按 ​

​Esc​

​ 退出編輯模式,這時左下角會有輸入框,輸入如下英文字元,注意冒号别打成中文字元,回車即可退出 ​

​vim​

​ 回到終端:

  • ​:w​

    ​:儲存
  • ​:q​

    ​:退出
  • ​:wq​

    ​:儲存并退出
  • ​!​

    ​​:強制的意思,不能儲存時 ​

    ​:w!​

    ​​ 強制儲存,不能退出時 ​

    ​:q!​

    ​​ 或 ​

    ​:wq!​

    ​ 強制退出

我們繼續 git

分支管理 branch/switch/checkout

一個人玩,可能分支的作用沒那麼大,但是團隊協作,離不開分支管理。

比如本文開頭圖檔那樣一個版本一個分支多友善,是吧

或者現有一個新需求一個頁面分為多個子產品,配置設定給多個人負責,每人做一個子產品,最後合并成一個完整的頁面,如果都在同一個分支上開發,各種邏輯互相穿插,那沖突真的是人都要搞麻了,如果每個人都建立一個分支,開發自己負責的那個功能,最後再合并到同一個分支上去就非常友善了

然後因為多人協作肯定不是在一台電腦上,是以就需要一個伺服器,來搭建一個 Git 倉庫服務,或者用公共的雲伺服器倉庫存儲,常見的代碼托管平台有比如:​

​Github​

​​、​

​碼雲(Gitee)​

​​、​

​騰訊工蜂​

​​、​

​GitLab​

​​、​

​Bitbucket​

​...,關于這個本篇文章不過多展開

建立分支

# 建立本地分支 test,但不切換
git branch test
# 建立 test 分支,并切換到 test 分支
git branch -M test
# 建立 test 分支,并切換到 test 分支
git checkout -b test
# 建立 test 分支,并切換到 test 分支
git switch -c test
# 建立本地與遠端對應的 test 分支,并切換到 test 分支,全稱最好一緻
git checkout -b test origin/test      

檢視分支

# 檢視所有本地分支
git branch
# 檢視所有遠端分支
git branch -r
# 檢視本地和遠端所有分支
git branch -a      

切換分支

​checkout​

​​ 和 ​

​switch​

​ 的共同點是都能切換分支,不同點是:

  • ​switch​

    ​ 語義上好點
  • ​switch​

    ​​ 僅僅用于切換和建立并切換,​

    ​checkout​

    ​ 還能用來還原工作區,後面進階那有介紹
# 切換到 test 分支
git checkout test
# 建立 test 分支,并切換到 test 分支
git checkout -b test

# 切換到 test 分支
git switch test
# 建立 test 分支,并切換到 test 分支
git switch -c test      

删除分支

# 删除本地 test 分支
git branch -d test
# 删除遠端主機的 master 分支
git push origin -d master      

重命名分支

# 把本地的 master 分支重命名為 test
git branch -m master test
# 遠端分支沒法直接重命名,隻能删了重建,主要分幾步
# 1. git push origin --delete test 删除遠端分支
# 2. git push origin newtest 上傳新的遠端分支
# 3. 把修改後的本地分支關聯遠端分支
git branch --set-upstream-to origin/newtest      

合并分支

其實就是上面的 ​

​git merge​

​​。比如要把 ​

​test​

​​ 分支合并到 ​

​master​

​ 分支,就:

# 先切換到 master 分支
git checkout master
# 拉一下,看有沒有更新
git pull
# 把 test 分支合進來
git merge test
# 檢視狀态,看有沒有沖突的,有就打開 IDE 解決一下
git status
# 然後 add、commit、push 幾個指令來一輪就 ok 了      

git commit 送出規範

​git commit​

​​ 送出規範指的就是 ​

​git commit -am 'xxxx'​

​​ 裡的 ​

​xxxx​

​ 的書寫規範,比如我在工作中開發了一個新功能送出的時候一般這麼寫:

  • ​git commit -am 'feat: 添加掃碼登入​

  • ​git commit -am 'feat(mobile):添加掃碼登入​

    ​,或者加個範圍說明是添加哪方面的功能

​feat​

​ 就是添加新功能的時候用,更多說明如下:

  • ​feat​

    ​:添加新功能
  • ​fix​

    ​:修複問題/BUG
  • ​style​

    ​:注意不是指CSS,而是修改了如空格、縮進、逗号等代碼風格相關,且不影響運作結果的
  • ​perf​

    ​:優化相關的,比如功能優化、性能提升、提升體驗等
  • ​refactor​

    ​:代碼重構,沒有加新功能或者修複 bug
  • ​revert​

    ​:撤消編輯,復原到上一個版本、撤銷上一次的 commit 之類的
  • ​test​

    ​:測試相關,比如單元測試、內建測試等
  • ​docs​

    ​:修改文檔/注釋,比如 README、CHANGELOG、CONTRIBUTE 等
  • ​chore​

    ​:依賴更新/腳手架配置修改等,比如有改變建構流程、或者增加依賴庫、工具之類的
  • ​workflow​

    ​:工作流程改進
  • ​ci​

    ​:持續內建
  • ​types​

    ​:類型定義檔案更改

到這裡,基礎部分内容就結束了

問個問題:​

​git branch -M ac​

​ 是啥意思?不許翻上面

進階操作

常用指令

裝*神器 alias

指令難記?沒有關系

咱們除了會寫一些别人看不懂的代碼,也可以敲一些别人看不懂的指令

​alias​

​​ 這個單詞想必大家就熟悉了,和項目中建立路徑别名類似,在 ​

​Git​

​ 裡是用來建立指令别名的,比如執行如下這指令後

// 配置全局 branch 指令别名為 b
git config --global alias.b branch      

然後比如想建立一個名為 ​

​test​

​ 的本地分支,如下即可

git b test      

好像有點邪教了,了解一下吧~

繼續工作中用到的

檢出 git checkout/git restore

# 四個都是:撤銷 test.js 從上次送出之後的所有修改
git checkout -- test.js
git checkout - test.js
git checkout test.js
git restore test.js

# 隻把 test.js 還原成上一個版本的,HEAD^表示上一個版本,HEAD^^上上一個版本
git checkout HEAD^ - test.js
# 隻把 test.js 重置到某個指定版本
git checkout commitID test.js
# 把 master 分支的 test.js 拿過來替換目前分支的 test.js
git checkout master - test.js

# 都是撤銷上一次 commit 之後的所有檔案的所有修改
git checkout -- *
git checkout -- .
git checkout .
git restore .

# 把暫存區的 test.js 重新放回工作區,和下面的 git reset HEAD test.js 作用一樣
git restore --staged test.js      

重置 git reset

​git reset​

​​ 通常用來把代碼重置到過去的某個版本,有五種模式(​

​--mixed​

​​、​

​--soft​

​​、​

​--hard​

​​、​

​--merge​

​),注意看注釋有說明差別。

另外 ​

​git reset​

​​ 比較暴力,要慎用,比如現在送出五次了,然後使用這個指令重置到第一次,那麼第二三四五次送出記錄會全部沒了的,找不回來的,這種情況記得建立個分支來執行這種操作就沒事了,或者使用 ​

​git revert​

# 後面一長串就是我複制的 commitID 或者說是 hash,長得就是這樣子的
# 等同于 git reset commitID,因為 --mixed 是預設模式,是以可以不寫
# 重置并撤銷 git commit 以及 git add,保留編輯器中所有修改
git reset --mixed afcfbcb940164de24cc4f8c866e1da3a18382e10

# 重置并撤銷 git commit,但不撤銷 git add,保留編輯器中所有修改
git reset --soft commitID

# 重置并撤銷 git commit 以及 git add,并且删除編輯器中所有修改
git reset --hard commitID

# 取消某次合并
git reset --merge commitID

git reset --keep commitID

# 把暫存區所有檔案退回到工作區,相當于撤銷 git add .
git reset HEAD
# 把暫存區的 test.js 重新放回工作區,和 git restore --staged test.js 作用一樣
git reset HEAD test.js
# 重置到上一個版本
git reset --hard HEAD^
# 重置到上上一個版本,以此類推
git reset --hard HEAD^^
# 重置到指定版本
git reset --hard commitID      

​commitID​

​ 可以通過三種方法檢視

  1. 執行 ​

    ​git log​

    ​​ 指令能看到目前分支本地所有送出記錄,上面每一條記錄都有對應一個 ​

    ​commitID​

  2. 去遠端代碼倉庫檢視曆史送出記錄,那裡每一條送出記錄都有一個對應的 ​

    ​commitID​

  3. ​git tag​

    ​​ 檢視标簽清單,如果有的話,再 ​

    ​git show 标簽名​

    ​​ 檢視标簽詳情,裡面也會有 ​

    ​commitID​

# 檢視目前分支所有送出記錄,詳細清單,一條記錄有幾行資訊
git log
# 檢視目前分支所有送出記錄,簡要清單,一條記錄一行
git log --pretty=oneline
# 
git log --oneline -n5      

另外關于叫法本地倉庫一般說重置、還原、撤銷都行,遠端倉庫一般叫復原

還原 git revert

​git revert​

​​ 和 ​

​git reset​

​​ 有點類似,隻是比 ​

​reset​

​ 稍微溫柔一點,沒那麼暴力。

上面介紹了假如現在是第五版,用 ​

​reset​

​​ 在重置回第一版本的時候,二三四五版全都會沒了,而 ​

​revert​

​ 重置回第一版的時候,隻是新增一條送出記錄“第六版”,代碼變成第一版的代碼,原本的一二三四五版記錄都會有

另外 revert 還要分兩種情況,一種是還原正常的 commit,也就是 git commit 送出的 commit,另一種是用 merge 合并的 commit,如下

# 第一種檢視正常送出的 commit,如下
git show 68be9e548
commit 68be9e548dadbe7b9677874b705662a8f95efd21

# 第二種檢視 merge 合并的 commit 如下,多了一行 Merge,後面指的是從哪兩個 commit 合并過來的
git show 9c810c1db
commit 9c810c1dbf72627dbff10d621c2974b32ed6d929
Merge: 3f6acb587 68be9e548      
# 撤銷正常送出的 commit
git revert commitID

# 撤銷 merge 的 commit 送出需要加參數來區分撤銷哪一個分支上的内容
# 也就是指定上面 Merge: 3f6acb587 68be9e548,這兩個 id 中的哪一個
# -m 接收一個參數是數字,取值 1 或 2,表示 Merge 的第一個還是第二個 id
git revert -m 1 9c810c1db      
# 删除最後一次遠端送出
git revert HEAD
git push origin master
或
git reset --hard HEAD^
git push origin master -f

# 還原某次送出
git revert commitID      

挑揀 git cherry-pick

比如有兩個分支 master 和 test,在 test 上修改了,并且送出了 commit 之後,這時候想把這次的送出也給弄到 master 上,就可以複制 test 的 commitID,再換到 master 分支後執行 ​

​git cherry-pick commitID​

​ 就可以了

what?這不就是 merge?

和 merge 不同的是:​

​cherry-pick​

​​ 合并的是某一次 ​

​commit​

​​ 送出的檔案,​

​merge​

​​ 合并的是整個分支。且 ​

​merge​

​​ 會額外多一條 ​

​merge commit​

​​ 的記錄,而 ​

​cherry-pick​

​ 不會。

而且 ​

​cherry-pick​

​ 更加靈活,在需要把某個/或多個分支中的 commit,合入其他分支的時候都可以用,示例如下

# 這樣就把其他分支的一個 commit 合入目前分支了
git cherry-pick commitID

# 如果需要把多個 commit 合過來如下,這多個 commitID 可以是來自不同分支的
git cherry-pick commitID1 commitID2 commitID3      

變基 git rebase

​git rebase​

​​ 和 ​

​git merge​

​ 的差別

git merge 和 git rebase 都是可以合并分支,合并用法也是一樣,不同的一個是在 commit 記錄的處理上:

  • ​git merge​

    ​ 會建立一條新的 commit,然後兩個分支以前的 commit 記錄都指向這個新 commit 記錄。這種方法會保留之前每個分支的 commit 曆史。
  • ​git rebase​

    ​會先找到兩個分支的第一個共同的 commit 祖先記錄,然後将提取目前分支這之後的所有 commit 記錄,放到目标分的最新送出後面。經過這個合并後,兩個分支合并後的 commit 記錄就變為了線性的記錄了。

這麼說可能不太好了解,看如下示例:

# 如下,需要把本地 test 分支合入 dev
# 為友善了解,字母表示commit記錄,數字表示送出時間順序,可以了解為1就是1點送出的
dev -> A1 -> B3 ->    這一行是遠端 dev 分支的commit記錄,A1/B3是你同僚送出的
      ↘ X2 -> Y4↗   這一行是拉取了 dev 分支後在本地的 test 分支 commit 記錄

# 現在需要把你本地的分支合并到遠端的分支去
# 用merge合并後,dev 分支看到的記錄是這樣的,M為merge記錄的commit
dev -> A1 -> X2 -> B3 -> Y4 -> M

# 用rebase合并後,dev 分支看到的記錄是這樣的,注意順序,且沒有合并記錄的commit
# 簡單說就是直接把 test 分支的所有新的 commit 拿出來直接拼到 dev 分支末尾,不管送出時間先後
dev -> A1 -> B3 -> X2 -> Y4      
  • 然後是解決沖突的問題上,merge 是解決一次沖突就行了,rebase 需要一次一次地解決,如上示例的記錄順序也能看出來
  • 再就是 ​

    ​rebase​

    ​ 可以合并多次 commit。比如本地分支送出了三個 commit,但沒有 push 到遠端,最後想送出到遠端的時候,為了簡潔,我們希望把本地的三個 commit 合并成一個 commit 再送出到遠端,遠端隻産生一條 commit 記錄,就可以用 ​

    ​git rebase -i​

    ​ 處理下先,這指令可以删除指定記錄,或者合并多個 commit,對 commit 消息編輯等
# 删除某次送出,^表示 commitID 的前一次送出
git rebase -i 'commitID'^
# 修改多個送出資訊
git rebase -i HEAD~3      

貯藏 git stash

​git stash​

​ 常用于把修改儲存起來,需要的時候再取出來。常用于:

  • 切換分支并且需要保留修改的時候
  • 切換分支并且需要把修改帶到新的分支的時候
# 把目前分支的修改儲存起來,兩個一樣的
git stash
git stash save
# 存儲并添加備注,友善查找
git stash save '備注資訊'
# 檢視儲存清單
git stash list
# 取出儲存中最近一次的修改并删除儲存記錄
git stash pop
# 取出儲存中的指定部分修改,stash@{0} 0是預設的不寫也行,是啥隻要檢視儲存清單你就知道了
git stash apply stash@{0}
# 删除指定儲存
git stash drop stash@{1}
# 删除所有的儲存
git stash clear
# 建立一個新分支 test,并恢複儲存工作時所在的送出到該分支上,并扔掉儲藏
git stash branch test stash@{1}
# 不儲存暫存區的,也就是 git add 了的
git stash --keep-index      

清理 git clean

和 ​

​git reset​

​ 的差別是:reset 删除的是己跟蹤的檔案,并且将已 commit 的回退。clean 删除的是未跟蹤的檔案/目錄

# 顯示如果執行後面删除的指令将會删除的檔案和目錄,相當于給提前給我們确認下
git clean -n
# 删除工作目錄中所有沒被追蹤的檔案(-f)以及空的子目錄(-d),一起就是 -df
git clean -df      

差異 git diff

用來找出倉庫或者檔案之間的差異,可以用來預測或者阻止可能産生沖突的合并

# 工作區 vs 暫存區
git diff
# 工作區 vs 版本庫
git diff head
# 暫存區 vs 版本庫
git diff –cached      

問題預防

  • 不要對已經送出到遠端倉庫的 commit 進行 rebase 變基操作,除非是你一個人玩的分支
  • 在切換分支,或者合并分支,或者重置/復原之前,最好不要有未 ​

    ​commit​

    ​​ 的檔案,如果有并且不想送出就用 ​

    ​git stash​

    ​ 先存起來,再執行操作,如果用指令操作的話,取出之後記得清理
  • 遠端倉庫復原前記得做好備份,比如拉一個分支在本地。并且需要通知團隊其他成員,不要悄摸摸地就搞了

解決問題

切換分支保留修改

有時候比如我們在 test 分支上開發了一半,由于某些原因需要切換到 master 分支,但現在又不想送出,又想保留修改并且不帶到 master 分支上去,就可以這樣:

# 把目前分支的修改儲存起來
git stash
# 切換到其他分支幹你的事
git checkout master
# 幹完了
# 切換回 test 分支
git checkout test
# 取出儲存中所有的修改
git stash pop
# 删除所有的儲存
git stash clear      

切換分支轉移修改

有的時候我們需要在 test 分支上開發,但是忘記了,活快幹完了才發現目前原來是 master 分支,可是已經開發了,這時候就需要切換分支到 test,并且把已經開發的部分内容也從 master 分支帶到 test 分支來,就可以這樣:

# 儲存修改
git stash
# 切換到 test 分支
git checkout test
# 取出儲存中的全部修改
git stash pop
# 或者
# 檢視儲存清單
git stash list
# 取出儲存中的指定部分修改,stash@{0} 是啥隻要檢視儲存清單你就知道了
git stash apply stash@{0}
# 再清掉儲存
git stash clear      

合并時發生沖突用 ​

​git merge abort​

​​ 或 ​

​git reset --merge​

​ 都可以取消合并

比如把不想要的代碼 commit 了,但是沒有 push

比如剛更新的代碼出問題了,需要還原這次送出的代碼

比如某次送出了不想送出的東西,需要清除掉它

revert 之後重新上線 diff 丢失

  • 比如在 dev 分到開發了個功能,送出後會産生一條 commit 記錄,為了友善了解,我們先把這次送出标記為 a
  • 然後合并到 master 後,我們把這次合并記錄标記為 b
  • 結果出現了 bug 需要撤銷合并,使用 revert b 撤銷了,這會産生了一條新的記錄 我們标記為 c
  • 然後繼續在 dev 分支開發完成送出,送出記錄标記為 d
  • 這時候再合并到 master 上去,此時合并後的内容不會包含 a 的送出,因為 a 被 revert 丢棄過,不會參與 diff,如果需要包含 a,需要先 revert c 意思是撤銷某一次的撤銷,再來合并,就 ok 了

合并沖突不想合并了

合并時、或者拉取時等,發現有沖突,可能是其他同僚送出的,自己不知道怎麼沖突怎麼選擇,或者其他原因,總之不想合并了,都可以用 ​

​--abort​

​ 取消,比如合并的時候發現有沖突不想合并了

​git merge --abort​

​ 取消合并即可

解決沖突

有的時候合并分支沖突是由于本地主分支沒有更新導緻,或者有時 ​

​git pull​

​ 的時候沖突,隻需要掉本地主分支,再重新拉一下遠端分支就好了。

# 隻保留 test 的修改
git checkout --theirs test.js
# 隻保留 master 的修改
git checkout --ours test.js
# 都保留
git checkout --ours/theirs test.js
# 檢視沖突,都行
git diff --theirs
git diff --ours

# 這個 --theirs 和 --ours 是啥?比如沖突的時候是這樣的
# <<<<<<<<< HEAD
# console.log('master') // 這個就是 --ours
# =========
# console.log('test') // 這個就是 --theirs
# >>>>>>>>> test