面試官:你知道git xx 和git xx的區別嗎?看完這篇Git指南後直呼:內行!

「本文已參與好文召集令活動,點擊查看:後端、大前端雙賽道投稿,2萬元獎池等你挑戰!前端

前言

做爲一名工程師,既然想要加入一個團隊,並肩做戰地協同開發項目,就必不可少要學會Git基本操做。面試過程當中,面試官不止是考察1-3年的工程師,高級崗位也一樣會考察團隊協做的能力。相信小夥伴們常常會在面試中被問到如下問題吧,能夠幫助你測試一下你的Git基礎牢不牢固。git

  • 代碼開發到一半,須要緊急切換分支修復線上問題,該怎麼辦?
  • 代碼合併有幾種模式?分別有什麼優缺點?
  • git fetchgit pull有什麼區別,有合併操做嗎?
  • git mergegit rebase有什麼區別,它們的應用場景有哪些?
  • git resetgit revert有什麼區別,該如何選擇,回滾後的<commit-id>還能找到嗎?

若是你心中已有答案,那麼能夠選擇跳過這篇文章啦,愉快地繼續摸魚~github

若是你對這些概念還有些模糊,或者沒有實際操做過,那麼就須要好好閱讀本篇文章啦!面試

接下來立刻進入正文啦,本文分四個部分介紹,你們能夠自由選擇閱讀。後端

  • Git的區域示例圖,幫助你們理解Git的結構。
  • Git的基本使用場景,介紹一些經常使用git命令。
  • Git的進階使用場景,介紹一些高頻出現的面試題目以及應用場景。
  • 最後介紹Git的下載地址、基本配置和工具推薦。

Git的區域

畫了一個簡單的示意圖,供你們參考緩存

yuque_diagram.jpg

  • 遠程倉庫(Remote):在遠程用於存放代碼的服務器,遠程倉庫的內容可以被分佈其餘地方的本地倉庫修改。
  • 本地倉庫(Repository):在本身電腦上的倉庫,平時咱們用git commit 提交到暫存區,就會存入本地倉庫。
  • 暫存區(Index):執行 git add 後,工做區的文件就會被移入暫存區,表示哪些文件準備被提交,當完成某個功能後須要提交代碼,能夠經過 git add 先提交到暫存區。
  • 工做區(Workspace):工做區,開發過程當中,平時打代碼的地方,看到是當前最新的修改內容。

Git的基本使用場景

如下命令遠程主機名默認爲origin,若是有其餘遠程主機,將origin替換爲其餘便可。bash

git fetch

# 獲取遠程倉庫特定分支的更新
git fetch origin <分支名>

# 獲取遠程倉庫全部分支的更新
git fetch --all
複製代碼

git pull

# 從遠程倉庫拉取代碼,併合併到本地,至關於 git fetch && git merge 
git pull origin <遠程分支名>:<本地分支名>

# 拉取後,使用rebase的模式進行合併
git pull --rebase origin <遠程分支名>:<本地分支名>
複製代碼

注意服務器

  • 直接git pull 不加任何選項,等價於git fetch + git merge FETCH_HEAD,執行效果就是會拉取全部分支信息回來,可是隻合併當前分支的更改。其餘分支的變動沒有執行合併。
  • 使用git pull --rebase 能夠減小衝突的提交點,好比我本地已經提交,可是遠程其餘同事也有新的代碼提交記錄,此時拉取遠端其餘同事的代碼,若是是merge的形式,就會有一個merge的commit記錄。若是用rebase,就不會產生該合併記錄,是將咱們的提交點挪到其餘同事的提交點以後。

git branch

# 基於當前分支,新建一個本地分支,但不切換
git branch <branch-name> 

# 查看本地分支
git branch

# 查看遠程分支
git branch -r

# 查看本地和遠程分支
git branch -a

# 刪除本地分支
git branch -D <branch-name>

# 基於舊分支建立一個新分支
git branch <new-branch-name> <old-branch-name> 

# 基於某提交點建立一個新分支
git branch <new-branch-name> <commit-id> 

# 從新命名分支
git branch -m <old-branch-name> <new-branch-name>
複製代碼

git checkout

# 切換到某個分支上
git checkout <branch-name>

# 基於當前分支,建立一個分支並切換到新分支上
git checkout -b <branch-name>
複製代碼

git add

# 添把當前工做區修改的文件添加到暫存區,多個文件能夠用空格隔開
git add xxx

# 添加當前工做區修改的全部文件到暫存區
git add .
複製代碼

git commit

# 提交暫存區中的全部文件,並寫下提交的概要信息
git commit -m "message"

# 相等於 git add . && git commit -m
git commit -am

# 對最近一次的提交的信息進行修改,此操做會修改commit的hash值
git commit --amend
複製代碼

git push

# 推送提交到遠程倉庫
git push 

# 強行推送到遠程倉庫
git push -f
複製代碼

git tag

# 查看全部已打上的標籤
git tag 

# 新增一個標籤打在當前提交點上,並寫上標籤信息
git tag -a <version> -m 'message' 

# 爲指定提交點打上標籤
git tag -a <version> <commit-id> 

# 刪除指定標籤
git tag -d <version> 
複製代碼

Git的進階使用場景

HEAD表示最新提交 ;HEAD^表示上一次; HEAD~n表示第n次(從0開始,表示最近一次)markdown

正常協做

  • git pull 拉取遠程倉庫的最新代碼
  • 工做區修改代碼,完成功能開發
  • git add . 添加修改的文件到暫存區
  • git commit -m 'message' 提交到本地倉庫
  • git push將本地倉庫的修改推送到遠程倉庫

代碼合併

git merge

自動建立一個新的合併提交點merge-commit,且包含兩個分支記錄。若是合併的時候遇到衝突,僅須要修改解決衝突後,從新commit。app

  • 場景:如dev要合併進主分支master,保留詳細的合併信息
  • 優勢:展現真實的commit狀況
  • 缺點:分支雜亂
git checkout master
git merge dev
複製代碼

rf1o2b6eduboqwkigg3w.gif

git merge 的幾種模式

  • git merge --ff (默認--ff,fast-farward)
    • 結果:被merge的分支和當前分支在圖形上併爲一條線,被merge的提交點commit合併到當前分支,沒有新的提交點merge
    • 缺點:代碼合併不衝突時,默認快速合併,主分支按時間順序混入其餘分支的零碎commit點。並且刪除分支,會丟失分支信息。
  • git merge --no-ff(不快速合併、推薦)
    • 結果:被merge的分支和當前分支不在一條線上,被merge的提交點commit還在原來的分支上,並在當前分支產生一個新提交點merge
    • 優勢:代碼合併產生衝突就會走這個模式,利於回滾整個大版本(主分支本身的commit點)
  • git merge --squash(把屢次分支commit歷史壓縮爲一次)
    • 結果:把屢次分支commit歷史壓縮爲一次

image.png

git rebase

  • 不產生merge commit,變換起始點位置,「整理」成一條直線,且能使用命令合併屢次commit。
  • 如在develop上git rebase master 就會拉取到master上的最新代碼合併進來,也就是將分支的起始時間指向master上最新的commit上。自動保留的最新近的修改,不會遇到合併衝突。並且可交互操做(執行合併刪除commit),可經過交互式變基來合併分支以前的commit歷史git rebase -i HEAD~3
  • 場景:主要發生在我的分支上,如 git rebase master整理本身的dev變成一條線。頻繁進行了git commit提交,可用交互操做drop刪除一些提交,squash提交融合前一個提交中。
  • 優勢:簡潔的提交歷史
  • 缺點:發生錯誤難定位,解決衝突比較繁瑣,要一個一個解決。
git checkout dev
git rebase master
複製代碼

dwyukhq8yj2xliq4i50e.gifmsofpv7k6rcmpaaefscm.gif

git merge和git rebase的區別

  • merge會保留兩個分支的commit信息,並且是交叉着的,即便是ff模式,兩個分支的commit信息會混合在一塊兒(按真實提交時間排序),多用於本身dev合併進master。
  • rebase意思是變基,改變分支的起始位置,在dev上git rebase master,將dev的屢次commit一塊兒拉到要master最新提交的後面(時間最新),變成一條線,多用於整理本身的dev提交歷史,而後把master最新代碼合進來。
  • 使用rebase仍是merge更多的是管理風格的問題,有個較好實踐:
    • 就是dev在merge進主分支(如master)以前,最好將本身的dev分支給rebase到最新的主分支(如master)上,而後用pull request建立普通merge請求。
    • 用rebase整理成重寫commit歷史,全部修改拉到master的最新修改前面,保證dev運行在當前最新的主branch的代碼。避免了git歷史提交裏無心義的交織。
  • 假設場景:從 dev 拉出分支 feature-a。
    • 那麼當 dev 要合併 feature-a 的內容時,使用 git merge feature-a
    • 反過來當 feature-a 要更新 dev 的內容時,使用 git rebase dev
  • git merge和git rebase 二者對比圖
    • git merge圖示 image.png
    • git rebase圖示 image.png

取消合併

# 取消merge合併
git merge --abort
# 取消rebase合併
git rebase --abort
複製代碼

代碼回退

代碼回退的幾種方式

  • git checkout
  • git reset
    • --hard:硬重置,影響【工做區、暫存區、本地倉庫】
    • --mixed:默認,影響【暫存區、本地倉庫】,被重置的修改內容還留在工做區
    • --soft:軟重置,影響 【本地倉庫】,被重置的修改內容還留在工做區和暫存區
  • git revert
# 撤回工做區該文件的修改,多個文件用空格隔開
git checkout -- <file-name>
# 撤回工做區全部改動
git checkout .

# 放棄已git add到暫存區的指定文件的緩存(HEAD表示最新版本)
git reset HEAD <file-name>
# 放棄全部的緩存
git reset HEAD .
# 丟棄已commit的其餘版本,hard參數表示同時重置工做區的修改
git reset --hard <commit-id>  
# 回到上一個commit的版本,hard參數表示同時重置工做區的修改
git reset --hard HEAD^

# 撤銷0ffaacc此次提交
git revert 0ffaacc     
# 撤銷最近一次提交
git revert HEAD       
# 撤銷最近2次提交,注意:數字從0開始
git revert HEAD~1      

# 回退後要執行強制推送遠程分支
git push -f 
複製代碼

git reset和git revert的區別

  • reset是根據來移動HEAD指針,在該次提交點後面的提交記錄會丟失。

hlh0kowt3hov1xhcku38.gif

  • revert會產生新的提交,來抵消選中的該次提交的修改內容,能夠理解爲「反作」,不會丟失中間的提交記錄。

3kkd2ahn41zixs12xgpf.gif

  • 使用建議
    • 公共分支回退使用git revert,避免丟掉其餘同事的提交。
    • 本身分支回退可以使用git reset,也可使用git revert,按需使用。

挑揀代碼

git cherry-pick

  • 「挑揀」提交,單獨抽取某個分支的一個提交點,將這個提交點的全部修改內容,搬運到你的當前分支。
  • 若是咱們只想將其餘分支的某個提交點合併進來,不想用git merge將全部提交點合併進來,就須要使用這個git cherry-pick
git cherry-pick <commit-id>
複製代碼

2dkjx4yeaal10xyvj29v.gif

暫存代碼

git stash

  • 當咱們想要切換去其餘分支修復bug,此時當前的功能代碼還沒修改完整,不想commit,就須要暫存當前修改的文件,而後切換到hotfix分支修復bug,修復完成再切換回來,將暫存的修改提取出來,繼續功能開發。
  • 還有另外一種場景就是,同事在遠程分支上推送了代碼,此時拉下來有衝突,能夠將咱們本身的修改stash暫存起來,而後先拉最新的提交代碼,再pop出來,這樣能夠避免一個衝突的提交點。
# 將本地改動的暫存起來
git stash 
# 將未跟蹤的文件暫存(另外一種方式是先將新增的文件添加到暫存區,使其被git跟蹤,就能夠直接git stash)
git stash -u 
# 添加本次暫存的備註,方便查找。
git stash save "message" 
# 應用暫存的更改
git stash apply 
# 刪除暫存
git stash drop 
# 應用暫存的更改,而後刪除該暫存,等價於git stash apply + git stash drop 
git stash pop
# 刪除全部緩存
git stash clear
# 查看緩存列表
git stash list
複製代碼

打印日誌

  1. git log

能夠顯示全部提交過的版本信息,若是感受太繁瑣,能夠加上參數  --pretty=oneline,只會顯示版本號和提交時的備註信息。

  1. git reflog

git reflog 能夠查看全部分支的全部操做記錄(包括已經被刪除的 commit 記錄和 reset 的操做),例如執行 git reset --hard HEAD~1,退回到上一個版本,用git log是看不出來被刪除的,用git reflog則能夠看到被刪除的,咱們就能夠買後悔藥,恢復到被刪除的那個版本。

Git的下載、配置、工具推薦

  • Git下載地址
  • 兩種拉取代碼的方式
    • https:每次都要手動輸入用戶名和密碼
    • ssh :自動使用本地私鑰+遠程的公鑰驗證是否爲一對祕鑰
  • 配置ssh
    • ssh-keygen -t rsa -C "郵箱地址"
    • cd ~/.ssh切換到home下面的ssh目錄、cat id_rsa.pub命令查看公鑰的內容,而後複製
    • github的settings -> SSH and GPG keys-> 複製剛纔的內容貼入 -> Add SSH key
    • 全局配置一下Git用戶名和郵箱
      • git config --global user.name "xxx"
      • git config --global user.email "xxx@xx.com"
      • image.png
  • Git 相關工具推薦
    • 圖形化工具 SourceTree :可視化執行git命令,解放雙手
    • VSCode插件 GitLens:能夠在每行代碼查看對應git的提交信息,並且提供每一個提交點的差別對比

結尾

閱讀到這裏,是否是感受對Git相關概念更加清晰了呢,那麼恭喜你,不再怕由於誤操做,丟失同事辛辛苦苦寫的代碼了,並且將在平常工做的協同中游刃有餘。

  • 💖建議收藏文章,工做中有須要的時候翻出來看一看~
  • 📃創做不易,若是個人文章對你有幫助,辛苦大佬們點個贊👍🏻,支持我一下~
  • 📌若是有錯漏,歡迎大佬們指正~
  • 👏歡迎轉載分享,請註明出處,謝謝~

參考

相關文章
相關標籤/搜索