一、Git基礎
1、Git簡介
Git是一種分布式版本控制系統,由Linux之父Linus開發。
所謂分布式版本管理系統,就是在每一台機器上都有一個完整的倉庫。
2、Git官網
Git官網:git
在官網上可以獲取Git的安裝軟件。
除此之外,還可以下載《progit》——這是最棒的Git學習資料,而且有中文版本。
3、Git安裝
從 https://git-scm.com/downloads
官方下載地址下載對應的操作系統版本一步步安裝即可。
4、Git基本配置
安裝完成之后,在任意目錄下,右鍵 Git Bash Here
全局配置郵箱和用戶名(–global
表示全局配置,也可以不配置,每個倉庫單獨配置)
$ git config --global user.name "test"
$ git config --global user.email test@qq.com
5、Git基本概念
5.1、Git工作區域
Git有四個工作區域:
-
工作區
簡單說工作區就是我們項目的目錄。
-
倉庫區/本地倉庫
工作區有一個
.git
目錄,其實這個不是工作區,是Git的版本庫,存儲了Git倉庫的所有版本信息 -
暫存區
暫存區域是一個文件,保存了下次將提交的文件列表信息,一般在 Git 倉庫目錄中。 有時候也被稱作“索引”,
不過一般說法還是叫暫存區域。
-
遠程倉庫
對於分布式版本管理系統,遠程倉庫不是必須存在的,但是通常項目都會有遠程倉庫。例如
Github
就是我們非常熟悉的遠程倉庫。基本的Git工作流程如下:
- 在工作目錄修改文件
- 暫存文件,將文件快照放入暫存區
- 提交更新,找到暫存區的文件,將快照永久性存儲到到 Git 倉庫區(本地)
- 將本地倉庫的變更推送到遠程倉庫
以上幾個區域的關系可以用下圖表示:
5.2、Git分支
分支是為了將修改記錄的整個流程分開存儲,讓分開的分支不受其它分支的影響,所以在同一個數據庫里可以同時進行多個不同的修改。
Git 為我們自動創建的第一個分支,也叫主分支,一般其它分支開發完成后都要合並到 master
5.3、Git文件狀態
在git中,文件主要有四種狀態:
-
Untracked: 未跟蹤, 此文件在文件夾中, 但並沒有加入到git庫, 不參與版本控制. 通過
git add
狀態變為Staged
. -
Unmodify(Committed): 文件已經入庫, 未修改, 即版本庫中的文件快照內容與文件夾中完全一致. 這種類型的文件有兩種去處, 如果它被修改, 而變為
Modified
. 如果使用git rm
移出版本庫, 則成為Untracked
文件 -
Modified: 文件已修改, 僅僅是修改, 並沒有進行其他的操作. 這個文件也有兩個去處, 通過
git add
可進入暫存staged
狀態, 使用git checkout
則丟棄修改過, 返回到unmodify
狀態, 這個git checkout
即從庫中取出文件, 覆蓋當前修改 -
Staged: 暫存狀態. 執行
git commit
則將修改同步到庫中, 這時庫中的文件和本地文件又變為一致, 文件為Unmodify
狀態. 執行git reset HEAD filename
取消暫存, 文件狀態為Modified
二、Git應用實踐
看完上面的Git基礎,你可能有一些迷惑,接下來,我們以實際工作中開發的流程來加深對Git的理解吧。
1、克隆項目
可以通過在工作區使用git init
來初始化一個Git倉庫,但通常開發中我們不會這樣做,因為實際的項目大部分已經進行了部分開發,並進行了版本管理,所以我們首先做的是從遠程倉庫克隆項目。
這里我從Gitee(一般開發項目的遠程倉庫是部署在內網的GitLab) fork
了一個開源項目,將這個項目作為遠程倉庫的項目:
點擊克隆下載
,可以看到項目的路徑,
-
HTTPS
是憑據式的路徑,使用此路徑,向遠程倉庫推送代碼的時候需要憑據(賬號密碼);這種方式向遠程倉庫提交,會要求賬號密碼,輸入完成之后,Win10操作系統可以選擇記住憑據,這樣就不用每一次都輸入了,Win10操作系統管理憑據
控制面板 → 用戶帳戶 → 憑據管理器 → Windows憑據
-
SSH
是秘鑰式的路徑,向遠程倉庫推送代碼的時候,需要本地的私鑰和遠程倉庫的公鑰對應。SSH配置可以參考 Windows配置Github、Gitee共存的Git環境,這里就不詳細展開講解。
我已經進行了公私鑰的配置,所以這里選擇SSH。
使用git clone
命令克隆項目
2、代碼管理
項目已經成功克隆,接下來要進行我們的開發了。
2.1、創建分支
通常開發不是在Master
分支上,而是在開發分支上,使用 git branch develop
創建一個新分支:
可以通過git branch
命令列出所有分支:
可以看到我們新建的分支。
2.2、切換分支
使用git checkout develop
命令切換到新建的develop分支:
2.3、添加文件到暫存區
接下來,我們再develop分支上進行一些開發操作,我這里對 redeme 進行了一些修改,需要把修改添加到暫存區。
-
首先通過
git status
命令查看工作區文件狀態 -
接下來使用
git add README.md
命令(可以使用git add .
添加所有修改)將更改添加到暫存區
可以看到文件已經添加。
2.4、提交修改到倉庫
接下來使用git commit -m "😀修改了redeme"
,將修改提交到倉庫
這里值得一提的是,我們的提交信息盡量遵循某種規范,例如在提交信息中體現本次提交的類型:
- feat :新功能
- fix : bug修復
- docs :文檔變更
- style :與樣式相關的所有變動
- refactor :既不是bug修復也未添加功能的代碼更改
- test :與測試有關所有變動
- chore :改變了構建任務,程序包管理器配置等
規范而精確的提交信息不僅能幫助我們的同事快速了解我們的提交,也對我們自己的開發和重構有很大的幫助。我喜歡用表情包標注提交類型,這樣從遠程倉庫看提交記錄比較好看😄
可以通過git log
命令查看提交歷史:
2.5、推送修改到遠程倉庫
可以使用git push origin develop
命令將修改推送到遠程倉庫,在推送之前,通常通過git pull origin develop
(本實例遠程倉庫不存在develop分支,所以直接推送)命令來拉取遠程倉庫——這個是為了避免本地版本落后的情況,當然如果沖突你也可以強制提交,只是你的同事會做出什么過激行為不敢保證。😂
在我們的遠程倉庫就可以看到這次提交了:
2.6、合並分支
最終我們的提交都是要合並到master
分支的,首先切換到master
分支,接着通過命令,git merge develop
命令,將develop
分支合並到master
。
我們這個分支是沒有沖突的,可能在合並的過程中會出現沖突的情況,可以通過 git status
查看沖突的文件,手動解決沖突。當然,可以借助一些開發工具來完成這個工作,下文再講。
2.7、版本回退
假如說,我們發現這次提交不是我們想要的,可以通過 git reset --hard HEAD^
回退到上一次提交
2.8、打標簽
假如我們要發布一個版本,我們通常會給這次提交打一個標簽 git tag publish/0.0.1
可以通過git tag
命令來查看我們打的標簽。
三、Git常用命令
在上面有這樣一張圖片,基本上日常使用記住這6個命令就可以了,但是要想熟練使用,可能就需要記住更多命令了,這里整理了一些常用的命令。
1、初始化倉庫
# 在當前目錄新建一個Git代碼庫
$ git init
# 新建一個目錄,將其初始化為Git代碼庫
$ git init [project-name]
# 下載一個項目和它的整個代碼歷史
$ git clone [url]
2、配置
Git的設置文件為.gitconfig,它可以在用戶主目錄下(全局配置),也可以在項目目錄下(項目配置)。
# 顯示當前的Git配置
$ git config --list
# 顯示 Git 的某一項配置
$ git config <key>
# 編輯Git配置文件
$ git config -e [--global]
# 設置提交代碼時的用戶信息,選擇global即全局配置
$ git config [--global] user.name "[name]"
$ git config [--global] user.email "[email address]"
3、增加/刪除文件
這里的增加/刪除文件指的是向暫存區增加/刪除文件。
# 查看文件狀態,查看當前工作區新增、更改或刪除的文件
$ git status
# 添加指定文件到暫存區,可以添加多個文件,中間以空格隔開
$ git add [file1] [file2] ...
# 添加指定目錄到暫存區,包括子目錄
$ git add [dir]
# 添加當前目錄的所有文件到暫存區
$ git add .
# 添加每個變化前,都會要求確認
# 對於同一個文件的多處變化,可以實現分次提交
$ git add -p
# 刪除工作區文件,並且將這次刪除放入暫存區
$ git rm [file1] [file2] ...
# 停止追蹤指定文件,但該文件會保留在工作區
$ git rm --cached [file]
# 改名文件,並且將這個改名放入暫存區
$ git mv [file-original] [file-renamed]
# 臨時保存修改,可跨分支
# save為可選項
$ git stash [save message]
# 所有保存的記錄列表
$ git stash list
# 恢復工作進度到工作區,此命令的stash@{num}是可選項,在多個工作進度中可以選擇恢復,不帶此項則默認恢復最近的一次進度相當於git stash pop stash@{0}
$ git stash pop [stash@{num}]
# 恢復工作進度到工作區且該工作進度可重復恢復,此命令的stash@{num}是可選項,在多個工作進度中可以選擇恢復,不帶此項則默認恢復最近的一次進度相當於git stash apply stash@{0}
$ git stash apply [stash@{num}]
# 刪除一條保存的工作進度,此命令的stash@{num}是可選項,在多個工作進度中可以選擇刪除,不帶此項則默認刪除最近的一次進度相當於git stash drop stash@{0}
$ git stash drop stash@{num}
# 刪除所有保存
$ git stash clear
4、代碼提交
# 提交暫存區到倉庫區,如果不加-m,會進入vim編輯器
$ git commit -m [message]
# 提交暫存區的指定文件到倉庫區
$ git commit [file1] [file2] ... -m [message]
# 提交工作區自上次commit之后的變化,直接到倉庫區
$ git commit -a
# 提交時顯示所有diff信息
$ git commit -v
# 使用一次新的commit,替代上一次提交
# 如果代碼沒有任何新變化,則用來改寫上一次commit的提交信息
$ git commit --amend -m [message]
# 重做上一次commit,並包括指定文件的新變化
$ git commit --amend [file1] [file2] ...
5、分支
# 列出所有本地分支
$ git branch
# 列出所有遠程分支
$ git branch -r
# 列出所有本地分支和遠程分支
$ git branch -a
# 新建一個分支,但依然停留在當前分支
$ git branch [branch-name]
# 新建一個分支,並切換到該分支
$ git checkout -b [branch]
# 新建一個分支,指向指定commit
$ git branch [branch] [commit]
# 新建一個分支,與指定的遠程分支建立追蹤關系
$ git branch --track [branch] [remote-branch]
# 切換到指定分支,並更新工作區
$ git checkout [branch-name]
# 切換到上一個分支
$ git checkout -
# 建立追蹤關系,在現有分支與指定的遠程分支之間
$ git branch --set-upstream [branch] [remote-branch]
# 合並指定分支到當前分支
$ git merge [branch]
# 查看分支合並狀態
$ git rerere status
# 顯示合並沖突解決方案的當前狀態——開始解決前與解決后的樣子
$ git rerere diff
# 選擇一個commit,合並進當前分支
$ git cherry-pick [commit]
#分支重命名
$ git git branch -m [oldName] [newName]
# 刪除分支
$ git branch -d [branch-name]
# 刪除遠程分支
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]
6、標簽
# 列出所有tag
$ git tag
# 新建一個tag在當前commit
$ git tag [tag]
# 新建一個tag在指定commit
$ git tag [tag] [commit]
# 刪除本地tag
$ git tag -d [tag]
# 刪除遠程tag
$ git push origin :refs/tags/[tagName]
# 查看tag信息
$ git show [tag]
# 提交指定tag
$ git push [remote] [tag]
# 提交所有tag
$ git push [remote] --tags
# 新建一個分支,指向某個tag
$ git checkout -b [branch] [tag]
7、查看信息
# 顯示有變更的文件
$ git status
# 顯示當前分支的版本歷史
$ git log
# 顯示commit歷史,以及每次commit發生變更的文件
$ git log --stat
# 搜索提交歷史,根據關鍵詞
$ git log -S [keyword]
# 顯示某個commit之后的所有變動,每個commit占據一行
$ git log [tag] HEAD --pretty=format:%s
# 顯示某個commit之后的所有變動,其"提交說明"必須符合搜索條件
$ git log [tag] HEAD --grep feature
# 顯示某個文件的版本歷史,包括文件改名
$ git log --follow [file]
$ git whatchanged [file]
# 顯示指定文件相關的每一次diff
$ git log -p [file]
# 顯示過去5次提交
$ git log -5 --pretty --oneline
# 顯示所有提交過的用戶,按提交次數排序
$ git shortlog -sn
# 顯示指定文件是什么人在什么時間修改過
$ git blame [file]
# 顯示暫存區和工作區的差異
$ git diff
# 顯示暫存區和上一個commit的差異
$ git diff --cached [file]
# 顯示工作區與當前分支最新commit之間的差異
$ git diff HEAD
# 顯示兩次提交之間的差異
$ git diff [first-branch]...[second-branch]
# 顯示今天你寫了多少行代碼
$ git diff --shortstat "@{0 day ago}"
# 顯示某次提交的元數據和內容變化
$ git show [commit]
# 顯示某次提交發生變化的文件
$ git show --name-only [commit]
# 顯示某次提交時,某個文件的內容
$ git show [commit]:[filename]
# 顯示當前分支的最近幾次提交
$ git reflog
8、遠程同步
# 克隆遠程倉庫
$ git clone [url]
# 下載遠程倉庫的所有變動
$ git fetch [remote]
# 顯示所有遠程倉庫
$ git remote -v
# 顯示某個遠程倉庫的信息
$ git remote show [remote]
# 增加一個新的遠程倉庫,並命名
$ git remote add [shortname] [url]
# 取回遠程倉庫的變化,並與本地分支合並
$ git pull [remote] [branch]
# 拉取遠程分支,同時創建本地分支
$ git fetch [remote] 遠程分支名x:本地分支名x
# 拉取遠程分支,同時創建本地分支,且切換到該分支
$ git checkout -b [branch] [origin/遠程分支名]
# git pull相當於以下兩步
# 1、拉取遠程分支
$ git fetch [remote] [branch]
# 2、合並到當前分支
git merge [remote/branch]
# 上傳本地指定分支到遠程倉庫
$ git push [remote] [branch]
# 強行推送當前分支到遠程倉庫,即使有沖突
$ git push [remote] --force
# 推送所有分支到遠程倉庫
$ git push [remote] --all
# 更新遠程分支列表
$ git remote update [remote] --prune
$ git remote update [remote] -p
# 刪除和遠程倉庫的關聯
$ git remote rm [remote]
9、撤銷
# 恢復暫存區的指定文件到工作區
$ git checkout [file]
# 恢復某個commit的指定文件到暫存區和工作區
$ git checkout [commit] [file]
# 恢復暫存區的所有文件到工作區
$ git checkout .
# 重置暫存區的指定文件,與上一次commit保持一致,但工作區不變
$ git reset [file]
# 重置暫存區與工作區,與上一次commit保持一致
$ git reset --hard
# 重置當前分支的指針為指定commit,同時重置暫存區,但工作區不變
$ git reset [commit]
# 回退到上一次提交
$ git reset --hard HEAD^
# 重置當前分支的HEAD為指定commit,同時重置暫存區和工作區,與指定commit一致
$ git reset --hard [commit]
# 重置當前HEAD為指定commit,但保持暫存區和工作區不變
$ git reset --keep [commit]
# 新建一個commit,用來撤銷指定commit
# 后者的所有變化都將被前者抵消,並且應用到當前分支
$ git revert [commit]
# 暫時將未提交的變化移除,稍后再移入
$ git stash
$ git stash pop
四、在開發工具中使用Git
在Git中一些操作例如解決沖突
、分支比較
等等使用圖形化的操作可能會更加方便快捷。
TortoiseGit是一款不錯的圖形化Git工具,是一個不錯的選擇,下載地址:https://tortoisegit.org/download/
當然,使用開發工具集成Git,也是一個不錯的選擇。
1、在IDEA中使用Git
IDEA是當前最好用的Java開發IDE,IDEA默認集成了對Git的支持,只需要配置設置執行程序即可。
1.1、配置Git
File
-->Settings
-->Version Control
-->Git
,修改Git執行路徑為自己安裝的Git路徑。
- 點擊Test,配置成功會提示Git版本信息
1.2、遠程操作
Idea中可以非常便捷的進行遠程倉庫相關的操作。
1.2.1、拉取代碼
通過Idea可以直接拉取遠程倉庫的代碼
File
-->New
--->Project From Version Controller
-->Git
- 填入遠程倉庫地址,選擇
Clone
這樣遠程倉庫的代碼就克隆到了本地。
1.2.2、拉取遠程分支
上面我們拉取的是遠程倉庫主干代碼,我們也可以拉取遠程分支代碼。右下角,點開分支。
可以看到 Remote Branchs
,下面就是遠程倉庫的分支。點擊遠程分支,Checkout As
,就可以把遠程分支拉到本地了。
1.2.3、更新代碼
我們在提交代碼前最好先更新下遠程倉庫的代碼到本地倉庫,這樣可以減少不必要的沖突,更新update可以直接通過快捷鍵 Ctrl + T
,也可以通過工具欄上按鍵來實現:
1.2.4、提交/推送代碼
在IDEA中開發好自己的代碼之后如何提交到遠程倉庫呢?右鍵項目
-->Git
- 1.Commit Directory:commit代碼(將stage區的暫存文件提交到當前分支的本地倉庫,並清空stage區),也可以push代碼(把本地倉庫的文件同步到遠程倉庫)。
-
- Commit對應Git的Commit命令,commit到本地倉庫
-
- Commit and Push也就是Commit和push,我們可以直接在這里commit到本地倉庫之后,再push到遠程倉庫。
在IDEA中,我們會看到文件被標識着不同顏色:紅色,綠色,藍色。它們分別代表什么意思呢?
紅色:未被版本控制的文件,即未添加到版本控制的文件,例如我們添加到ignore中的文件。
綠色:新加入版本的文件,即我們新創建的文件,還未提交到遠程倉庫。
藍色:修改過的文件,即遠程倉庫中已有該文件,我們這次對它進行了修改,但是還未提交。
這里再接着看看幾個按鍵的作用:
2.Add:把本地文件從工作目錄添加到本地倉庫的stage區,對應Git的Add命令。
3.Compare with Branch…:與遠程分支比較。我們提交前可以通過此功能比較下我們工作目錄中代碼和遠程分支代碼的異同。
4.Show History:查看歷史修改版本記錄。
5.Revert:回滾,會將你的本地修改回滾。
6.Repository:各種倉庫命令。
1.3、分支管理
1.3.1、新建分支
點擊New Branch可以新建分支
1.3.2、分支切換/比較/合並/重命名/刪除
在Idea中這些功能的使用也常簡單,點擊分支,點擊要操作的分支,就可以看到這些選項
1.4、查看提交歷史
再Version Controller
里log
可以查看提交歷史
1.5、合並(處理沖突)
上面我們提了分支合並,可以從本地分支合並,也可以從遠程倉庫合並,一般兩個並行開發的分支合並都是會有沖突,Idea中合並沖突是非常方便的。
- 在合並過程中發生了沖突,Idea會提示沖突,選擇
Merge
- Idea提供了三個分欄,我們可以點擊箭頭,很方便地處理沖突
- 如果合並時沒有處理,也可以在
Version Controller
中處理
2、在VS Code中使用Git
VS Code是當前最流行的前端開發工具,VS Code對Git的支持不是那么強大,但是可以通過插件來增強Git功能。
2.1、基本使用
2.1.1、基本界面
我的VS Code配置了中文包。
點擊左側Git標識,可以看到很多的操作。
2.1.2、文件狀態
當對文件進行修改后,有三種狀態
- M 是 modify 的縮寫即該文件存在修改
- D 是 delete 的縮寫即該文件被刪除了
- U 是 Update 的縮寫即該文件是新添加
2.1.3、提交代碼
文件按鈕的的意思。
- 如果是新添加的文件,放棄修改就會提示徹底刪除文件。
- 如果是刪除的文件,選擇放棄修改就會從倉庫中恢復文件 (再也不用擔心誤刪的文件找不到了)
- 點擊 + 號確認文件的修改就會提到 stash Changes 上
(對應 git add 命令)
確認了文件之后,在輸入框輸入這次更新的內容,然后點擊打勾就可以保存這一次更新了 (對應 git commit 命令)
如果當前所有的 Changes 都要 commit ,那可以直接輸入上傳的信息並且打勾就可以快速 commit 了。
2.1.4、推送代碼
完成提交以后,vscode 的左下角就會出現上箭頭的數字為 1 (上箭頭是 push 的更新,下箭頭是可以 pull 的更新)
當然如果之前沒有 push 過代碼的話,這個可能會沒有數字顯示。
這個時候就可以將代碼推送到 遠程倉庫上了 (對應 git push 命令)
OK,遠程倉庫就可以看到我們的提交了。
2.1.5、拉取代碼
也可以通過 vscode 左下角的下箭頭看到倉庫是否可以 拉取,然后點擊菜單的 git pull 進行倉庫更新 (對應 git pull
命令)
2.1.5、分支切換
vscode 可以直接在左下角創建分支,也可以切換分支。
上面的功能滿足了基本要求,如果還需要
代碼比對
,解決沖突
,可以選擇插件,目前公認的最好用的插件是GitLens。
2.2、使用Git插件
2.2.1、安裝GitLens
打開插件商店,搜索 GitLens
,安裝即可。
2.2.2、GitLens基本使用
安裝完成之后側邊的工具欄會多出一個 git 分支圖標,點擊就可以查看更詳細的信息了。
- 第一個折疊面板查看所有提交
- 第二個折疊面板查看當前打開文件的歷史
- 第三個折疊面板查看分支
- 第四個折疊面板查看遠程
- 第五個折疊面板查看stash的文件
- 第六個折疊面板查看標簽
- 第七個折疊面板可以比較不同的分支標簽的文件區別
同時發現,每一行代碼都會顯示提交人和提交信息
2.2.3、查看更改
修改文件后,Gitlens 側邊會有顏色塊告訴你代碼的更新情況:
- 紅色箭頭表示刪除
- 藍色塊表示修改
- 綠色塊表示增添
在右上角點擊查看更改
,可以查看當前文件的更改。
2.2.4、處理沖突
VScode 內置的 git 會告訴你有沖突的文件,然后通過 Gitlens 可以快速調整沖突。
參考
【1】:Git 從入門到放不下
【2】:常用Git命令整理
【3】:Git分支管理策略
【4】:vue-blog
【5】:《progit》