Git
一、什么是 Git
1. 概念
Git(讀音為/g ?t/)是一個開源的分布式版本控制系統(tǒng),可以有效、高速地處理從很小到非常大的項(xiàng)目版本管理。 也是 Linus Torvalds 為了幫助管理 Linux 內(nèi)核開發(fā)而開發(fā)的一個開源的版本控制軟件。
版本控制工具是踐行 devops 理念,CI/CD 中的一個環(huán)節(jié),是自動化測試工程師不可或缺的一門技術(shù)。
2. github,gitee,gitlab 的區(qū)別
- GitHub 是一個面向開源及私有軟件項(xiàng)目的托管平臺,因?yàn)橹恢С?Git 作為唯一的版本庫格式進(jìn)行托管,故名 GitHub。
- Gitee 是開源中國(OSChina)推出的基于 Git 的代碼托管服務(wù),是國內(nèi)的 GitHub。
- GitLab 是一個用于代碼倉庫管理系統(tǒng)的開源項(xiàng)目,使用 Git 作為代碼管理工具,并在此基礎(chǔ)上搭建起來的 Web 服務(wù)。
二、Git 的使用
1. 本地操作
1.1 安裝
在 Linux 上安裝
如果你想在 Linux 上用二進(jìn)制安裝程序來安裝基本的 Git 工具,可以使用發(fā)行版包含的基礎(chǔ)軟件包管理工具來安裝。 以 Fedora 為例,如果你在使用它,你可以使用 dnf:
$ sudo dnf install git-all
如果你在基于 Debian 的發(fā)行版上,如 Ubuntu,請使用 apt:
$ sudo apt install git-all
要了解更多選擇,Git 官方網(wǎng)站上有在各種 Unix 發(fā)行版的系統(tǒng)上的安裝步驟,網(wǎng)址為 https://git-scm.com/download/linux。
在 macOS 上安裝
在 Mac 上安裝 Git 有多種方式。 最簡單的方法是安裝 Xcode Command Line Tools。 Mavericks (10.9) 或更高版本的系統(tǒng)中,在 Terminal 里嘗試首次運(yùn)行 Git 命令即可。
$ git --version
如果沒有安裝過命令行開發(fā)者工具,將會提示你安裝。
在 Windows 上安裝
在 Windows 上安裝 Git 也有幾種安裝方法。 官方版本可以在 Git 官方網(wǎng)站下載。 打開 https://git-scm.com/download/win,下載會自動開始。雙擊下載的安裝文件,按照引導(dǎo)程序安裝即可。
1.2 初次配置
安裝完 Git 之后,要做的第一件事就是設(shè)置你的用戶名和郵件地址。 這一點(diǎn)很重要,因?yàn)槊恳粋€ Git 提交都會使用這些信息,它們會寫入到你的每一次提交中,不可更改,在終端運(yùn)行如下命令:
git config --global user.name "zlf"
git config --global user.email "zlf@163.com"
加了 --global 表示全局設(shè)置,且只需要設(shè)置一次。
1.3 初始化倉庫
如果你有一個尚未進(jìn)行版本控制的項(xiàng)目目錄,想要用 Git 來控制它,那么首先需要進(jìn)入該項(xiàng)目目錄中。之后執(zhí)行命令:
$ git init
該命令將創(chuàng)建一個名為 .git 的子目錄,這個子目錄含有你初始化的 Git 倉庫中所有的必須文件,這些文件是 Git 倉庫的骨干。請不要修改它。
1.4 添加文件進(jìn)行跟蹤
上面的操作,我們僅僅是做了一個初始化的操作,項(xiàng)目里的文件還沒有被跟蹤。
如果在一個已存在文件的文件夾(而非空文件夾)中進(jìn)行版本控制,現(xiàn)在應(yīng)該開始追蹤這些文件了。 可以通過 git add 命令來指定所需的文件來進(jìn)行追蹤。
$ git add *.py
$ git add LICENSE
1.5 提交文件到倉庫
要將上一個步驟中追蹤的文件提交到倉庫,運(yùn)行命令 git commit。這樣會啟動文本編輯器來輸入提交說明。
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
#
# Initial commit
#
# Changes to be committed:
# new file: LICENSE
# new file: test.py
#
~
~
~
~
~
~
~
~
~
~
<sers/men85/Desktop/study/.git/COMMIT_EDITMSG [unix] (21:15 13/09/2021)1,0-1 All
"C:/Users/men85/Desktop/study/.git/COMMIT_EDITMSG" [unix] 12L, 251C
也可以在 commit 命令后添加 -m 選項(xiàng),將提交信息與命令放在同一行
git commit -m "init"
1.6 Git 的三種狀態(tài)
Git 有三種狀態(tài),你的文件可能處于其中之一: 已提交(committed)、已修改(modified) 和 已暫存(staged)。
- 已修改表示修改了文件,但還沒保存到數(shù)據(jù)庫中。
- 已暫存表示對一個已修改文件的當(dāng)前版本做了標(biāo)記,使之包含在下次提交的快照中。
- 已提交表示數(shù)據(jù)已經(jīng)安全地保存在本地?cái)?shù)據(jù)庫中。
這會讓我們的 Git 項(xiàng)目擁有三個階段:工作區(qū)、暫存區(qū)以及 Git 目錄。
- 工作區(qū)即是項(xiàng)目的根目錄,是你工作的區(qū)域,是對項(xiàng)目的某個版本獨(dú)立提取出來的內(nèi)容。 這些從 Git 倉庫的壓縮數(shù)據(jù)庫中提取出來的文件,放在磁盤上供你使用或修改。
- 暫存區(qū)是一個文件,保存了下次將要提交的文件列表信息,一般在 Git 倉庫目錄中。 按照 Git 的術(shù)語叫做“索引”,不過一般說法還是叫“暫存區(qū)”。
- Git 倉庫目錄是 Git 用來保存項(xiàng)目的元數(shù)據(jù)和對象數(shù)據(jù)庫的地方。 這是 Git 中最重要的部分,從其它計(jì)算機(jī)克隆倉庫時,復(fù)制的就是這里的數(shù)據(jù)。
基本的 Git 工作流程如下:
- 在工作區(qū)中修改文件。
- 將你想要下次提交的更改選擇性地暫存,這樣只會將更改的部分添加到暫存區(qū)。
git add - 提交更新,找到暫存區(qū)的文件,將快照永久性存儲到 Git 目錄。
git commit
1.7 檢查當(dāng)前文件狀態(tài)
你工作目錄下的每一個文件都不外乎這兩種狀態(tài):已跟蹤 或 未跟蹤。 已跟蹤的文件是指那些被納入了版本控制的文件,在上一次快照中有它們的記錄,在工作一段時間后, 它們的狀態(tài)可能是未修改,已修改或已放入暫存區(qū)。簡而言之,已跟蹤的文件就是 Git 已經(jīng)知道的文件。編輯過某些文件之后,由于自上次提交后你對它們做了修改,Git 將它們標(biāo)記為已修改文件。 在工作時,你可以選擇性地將這些修改過的文件放入暫存區(qū),然后提交所有已暫存的修改,如此反復(fù)。
可以用 git status 命令查看哪些文件處于什么狀態(tài)。如果所有文件沒有修改,且都已經(jīng)提交到本地?cái)?shù)據(jù)庫,也及時工作區(qū),暫存區(qū),Git 倉庫一致,你會看到類似這樣的輸出:
$ git status
On branch master
nothing to commit, working tree clean
現(xiàn)在,讓我們在項(xiàng)目下創(chuàng)建一個新的 README 文件。 如果之前并不存在這個文件,使用 git status 命令,你將看到一個新的未跟蹤文件:
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
README
nothing added to commit but untracked files present (use "git add" to track)
現(xiàn)在我們來修改一個已被跟蹤的文件。 如果你修改了一個名為 test.py 的已被跟蹤的文件,然后運(yùn)行 git status 命令,會看到下面內(nèi)容:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: test.py
Untracked files:
(use "git add <file>..." to include in what will be committed)
README
no changes added to commit (use "git add" and/or "git commit -a")
我們在練習(xí)一下 Git 的工作流程,將增加的文件和修改的內(nèi)容提交到 Git 倉庫。
$ git add .
$ git commit -m "練習(xí)"
[master 2852e80] 緇冧範(fàn)
2 files changed, 1 insertion(+)
create mode 100644 README
當(dāng)想要跟蹤目錄下所有的文件時可以運(yùn)行命令 git add .
1.8 查看提交記錄
在提交了若干更新,你也許想回顧下提交歷史。 完成這個任務(wù)最簡單而又有效的工具是 git log 命令。例如在我的帶班課件項(xiàng)目中運(yùn)行 git log 命令時,可以看到下面的輸出:
$ git log
commit 304b472cab3fcff5c220bf3e8e91a2e2fa642003 (HEAD -> master, origin/master)
Author: xinlan <117220100@qq.com>
Date: Thu Aug 26 14:05:00 2021 +0800
日常
commit 65f23a537366f35bd99047438c40547278294028
Author: xinlan <117220100@qq.com>
Date: Fri Aug 6 21:18:35 2021 +0800
haha
commit eca023381f42ce0428ab45c0a8b33621dd2cc6f8
Author: xinlan <117220100@qq.com>
Date: Sat May 29 19:19:24 2021 +0800
py38 day43
不傳入任何參數(shù)的默認(rèn)情況下,git log 會按時間先后順序列出所有的提交,最近的更新排在最上面。git log 命令還有很多參數(shù),用來搜索和顯示。
其中一個非常有用的參數(shù)是 --pretty。 這個參數(shù)可以使用不同于默認(rèn)格式的方式展示提交歷史。 這個選項(xiàng)有一些內(nèi)建的子選項(xiàng)供你使用。 比如 oneline 會將每個提交放在一行顯示,在瀏覽大量的提交時非常有用。 另外還有 short,full 和 fuller 選項(xiàng),它們展示信息的格式基本一致,但是詳盡程度不一:
$ git log --pretty=oneline
304b472cab3fcff5c220bf3e8e91a2e2fa642003 (HEAD -> master, origin/master) 日常
65f23a537366f35bd99047438c40547278294028 haha
eca023381f42ce0428ab45c0a8b33621dd2cc6f8 py38 day43
1b174b1486bae0554ff8a79acca55369387480f9 py41 day2
5ae08fa293a9a6bd7eddf8cb365e07cc221f0c07 py38day42
6fe8725de1151455f25e069ad80357edf5c4d6b0 'py38day41'
2effcc5dc6670a23cdbf4049321923b735ae3f16 add 41
2. 遠(yuǎn)程操作
2.1 創(chuàng)建遠(yuǎn)程倉庫
遠(yuǎn)程倉庫是指托管在因特網(wǎng)或其他網(wǎng)絡(luò)中的你的項(xiàng)目的版本庫。
要創(chuàng)建自己的遠(yuǎn)程倉庫,最簡單的方法是在 gitee(碼云),或 GitHub 上創(chuàng)建一個遠(yuǎn)程倉庫。這里推薦使用碼云,中文且速度快,下面以碼云為例。碼云地址 https://gitee.com/,注冊賬號請自理。
注冊并登錄碼云后,點(diǎn)擊右上角的加號,選擇新建倉庫
進(jìn)入新建倉庫頁面,填寫必要選項(xiàng)后,點(diǎn)擊創(chuàng)建
倉庫創(chuàng)建成功后會出現(xiàn)下面的頁面,包含倉庫的地址和一些幫助信息
2.2 添加遠(yuǎn)程倉庫
運(yùn)行 git remote add <shortname> <url> 添加一個新的遠(yuǎn)程 Git 倉庫,同時指定一個方便使用的簡寫。運(yùn)行
$ git remote add origin git@gitee.com:wcflove/study.git
這會給當(dāng)前本地倉庫添加一個遠(yuǎn)程倉庫,地址為 git@gitee.com:wcflove/study.git,遠(yuǎn)程倉庫地址的簡寫為 origin(你可以取你想要的名字)。
運(yùn)行 git remote -v 命令可以查看遠(yuǎn)程倉庫信息,一個本地倉庫可以有多個遠(yuǎn)程倉庫。
git刪除倉庫指令 git remote re <shortname>
$ git remote -v
gitee git@gitee.com:wcflove/study.git (fetch)
gitee git@gitee.com:wcflove/study.git (push)
2.3 推送到遠(yuǎn)程倉庫
通過命令 git push <remote> <branch> 可以將你的本地項(xiàng)目推送到遠(yuǎn)程倉庫。當(dāng)你想要將 master 分支(關(guān)于分支我們后面再詳細(xì)討論)推送到 origin 服務(wù)器時(再次說明,克隆時通常會自動幫你設(shè)置好那兩個名字), 那么運(yùn)行這個命令就可以將你所做的備份到服務(wù)器:
$ git push origin master
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 481 bytes | 481.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.1]
To gitee.com:wcflove/study.git
* [new branch] master -> master
注意:這一步操作需要驗(yàn)證你的權(quán)限,如果在添加遠(yuǎn)程倉庫時,使用的是 https 協(xié)議的地址,那么需要你輸入用戶名和密碼。如果使用的是 ssh 協(xié)議地址,那么需要配置 ssh 的公鑰(詳見碼云幫助文檔)。
推送成功后刷新你的遠(yuǎn)程倉庫,你會看到剛剛推送上去的文件。
2.4 從遠(yuǎn)程倉庫中拉取
從遠(yuǎn)程倉庫中獲得數(shù)據(jù),可以執(zhí)行:
$ git pull <remote>
這個命令會訪問遠(yuǎn)程倉庫,從中拉取所有你還沒有的數(shù)據(jù),并自動合并該遠(yuǎn)程分支到當(dāng)前分支。
2.5 克隆遠(yuǎn)程倉庫
運(yùn)行命令 git clone <url> 會將遠(yuǎn)程倉庫下載到當(dāng)前目錄。例如:
git clone git@gitee.com:wcflove/study.git
這會在當(dāng)前目錄創(chuàng)建 study 文件夾,并在這個目錄下初始化一個 .git 文件夾,自動將地址 git@gitee.com:wcflove/study.git 添加為遠(yuǎn)程倉庫并默認(rèn)以 “origin” 為簡寫, 自動設(shè)置本地 master 分支跟蹤克隆的遠(yuǎn)程倉庫的 master 分支,并從遠(yuǎn)程倉庫拉取 master 分支下所有數(shù)據(jù)放入 .git 文件夾,然后從中讀取最新版本的文件的拷貝。
3. 分支操作
3.1 分支簡介
幾乎所有的版本控制系統(tǒng)都以某種形式支持分支。 使用分支意味著你可以把你的工作從開發(fā)主線上分離開來,以免影響開發(fā)主線。
為了真正理解 Git 處理分支的方式,我們需要回顧一下 Git 是如何保存數(shù)據(jù)的。Git 保存的不是文件的變化或者差異,而是一系列不同時刻的 快照 。在進(jìn)行提交操作時,Git 會保存一個提交對象(commit object)。該提交對象會包含一個指向暫存內(nèi)容快照的指針,還包含了作者的姓名和郵箱、提交時輸入的信息以及指向它的父對象的指針。 首次提交產(chǎn)生的提交對象沒有父對象,普通提交操作產(chǎn)生的提交對象有一個父對象, 而由多個分支合并產(chǎn)生的提交對象有多個父對象。
Git 的分支,其實(shí)本質(zhì)上僅僅是指向提交對象的可變指針。 Git 的默認(rèn)分支名字是 master。 在多次提交操作之后,你其實(shí)已經(jīng)有一個指向最后那個提交對象的 master 分支。 master 分支會在每次提交時自動向前移動。
3.2 創(chuàng)建分支
創(chuàng)建分支非常簡單,它只是為你創(chuàng)建了一個可以移動的新的指針。 比如,創(chuàng)建一個 testing 分支, 你需要使用 git branch 命令:
$ git branch testing
這會在當(dāng)前所在的提交對象上創(chuàng)建一個指針。
Git 中有一個名為 HEAD 的特殊指針,指向當(dāng)前所在的本地分支(譯注:將 HEAD 想象為當(dāng)前分支的別名)。 在本例中,你仍然在 master 分支上。 因?yàn)?git branch 命令僅僅 創(chuàng)建 一個新分支,并不會自動切換到新分支中去。
3.3 切換分支
要切換到一個已存在的分支,你需要使用 git checkout 命令。 我們現(xiàn)在切換到新創(chuàng)建的 testing 分支去:
$ git checkout testing
這樣 HEAD 就指向 testing 分支了。
3.4 合并分支
當(dāng)我們在 testing 分支上工作并形成了一些列提交后,可以切換回 master 分支,然后運(yùn)行 git merge 命令:
$ git checkout master
$ git merge testing
將其合并到 master 分支上。
3.5 解決沖突
有時候合并操作不會如此順利。 如果你在兩個不同的分支中,對同一個文件的同一個部分進(jìn)行了不同的修改,Git 就沒法干凈的合并它們。
$ git merge testing
Auto-merging test.py
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
此時 Git 做了合并,但是沒有自動地創(chuàng)建一個新的合并提交。 Git 會暫停下來,等待你去解決合并產(chǎn)生的沖突。 你可以在合并沖突后的任意時刻使用 git status 命令來查看那些因包含合并沖突而處于未合并(unmerged)狀態(tài)的文件:
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: test.py
no changes added to commit (use "git add" and/or "git commit -a")
任何因包含合并沖突而有待解決的文件,都會以未合并狀態(tài)標(biāo)識出來。 Git 會在有沖突的文件中加入標(biāo)準(zhǔn)的沖突解決標(biāo)記,這樣你可以打開這些包含沖突的文件然后手動解決沖突。 出現(xiàn)沖突的文件會包含一些特殊區(qū)段,看起來像下面這個樣子:
<<<<<<< HEAD:test.py
print('hello world!')
=======
print("hello world!")
>>>>>>> dev:test.py
這表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因?yàn)槟阍谶\(yùn)行 merge 命令的時候已經(jīng)切換到了這個分支)在這個區(qū)段的上半部分(======= 的上半部分),而 dev 分支所指示的版本在 ======= 的下半部分。 為了解決沖突,你必須選擇使用由 ======= 分割的兩部分中的一個,或者你也可以自行合并這些內(nèi)容。
例如,你可以通過把這段內(nèi)容換成下面的樣子來解決沖突:
print("hello world!")
上述的沖突解決方案僅保留了其中一個分支的修改,并且 <<<<<<< , ======= , 和 >>>>>>> 這些行被完全刪除了。 在你解決了所有文件里的沖突之后,對每個文件使用 git add 命令來將其標(biāo)記為沖突已解決。 一旦暫存這些原本有沖突的文件,Git 就會將它們標(biāo)記為沖突已解決。
你可以再次運(yùn)行 git status 來確認(rèn)所有的合并沖突都已被解決:
$ git status
On branch master
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: test.py
如果你對結(jié)果感到滿意,并且確定之前有沖突的的文件都已經(jīng)暫存了,這時你可以輸入 git commit 來完成合并提交。
- git config user.name 查看用戶名
git config user.email 查看郵箱 - git config --global user.name "xxx" 切換用戶。
git config --global user.email "xxx" 切換郵箱。
今天在使用git add 命令的時候,彈出了一個警告 warning: LF will be replaced by CRLF in ******(具體的一個文件)
原因
LF和CRLF其實(shí)都是換行符,但是不同的是,LF是linux和Unix系統(tǒng)的換行符,CRLF是window 系統(tǒng)的換行符。這就給跨平臺的協(xié)作的項(xiàng)目帶來了問題,保存文件到底是使用哪個標(biāo)準(zhǔn)呢? git為了解決這個問題,提供了一個”換行符自動轉(zhuǎn)換“的功能,并且這個功能是默認(rèn)處于”自動模式“即開啟狀態(tài)的。
這個換行符自動轉(zhuǎn)換會把自動把你代碼里 與你當(dāng)前操作系統(tǒng)不相同的換行的方式 轉(zhuǎn)換成當(dāng)前系統(tǒng)的換行方式(即LF和CRLF 之間的轉(zhuǎn)換),這樣一來,當(dāng)你提交代碼的時候,即使你沒有修改過某個文件,也被git認(rèn)為你修改過了,從而提示"LF will be replaced by CRLF in *****"
解決
最簡單的一種辦法就是把自動轉(zhuǎn)換功能關(guān)掉即可。
輸入命令 :git config core.autocrlf false (僅對當(dāng)前git倉庫有效)
git config --global core.autocrlf false (全局有效,不設(shè)置推薦全局)
Git解決沖突的方法
1、使用git fetch origin master將遠(yuǎn)程分支拉下來
2、使用git merge origin master手動合并沖突的內(nèi)容,首先合并代碼并輸入備注信息,然后按esc,再按shit+;,輸入wq保存并退出
3、使用git add xxx和git commit -m "xxx" 將改動提交
4、使用git push origin master將改動提交到遠(yuǎn)程分支