東莞市國外網(wǎng)站建設(shè)報價百度云盤資源搜索
文章目錄
- 基本操作
- 創(chuàng)建git倉庫
- 配置name和email
- .git目錄的結(jié)構(gòu)
- git add & git commit
- .git目錄結(jié)構(gòu)的變化
- git追蹤管理的數(shù)據(jù)
- git的版本回退
- 回退的原理
- 回退的三種情況
- 版本庫中文件的刪除
- git分支管理
- 分支的刪除
- 合并分支時的沖突
- 分支的合并模式
- 分支策略
- git stash
- 不要在master分支上解決沖突
- git的遠(yuǎn)程操作
- 將修改提交到遠(yuǎn)程倉庫
- push時忽略特殊文件
- 配置命令的別名
- git的標(biāo)簽管理
- 推送標(biāo)簽
- git實戰(zhàn)
- 同一分支下的多人協(xié)作(不推薦)
- 不同分支下的多人協(xié)作
- 為什么本地依然能看到遠(yuǎn)端已經(jīng)刪除的分支?
- git flow模型
git作為目前最主流的版本控制器,可以控制電腦中所有格式的文件
對于開發(fā)人員來說,通常使用git維護(hù)項目的源文件
那么什么是版本控制器?版本控制器是一個管理系統(tǒng),用來記錄每次的修改以及版本迭代(每次的版本數(shù)據(jù))
基本操作
創(chuàng)建git倉庫
要想使用git的版本控制,就需要創(chuàng)建一個git倉庫,只有在倉庫中的文件才會被git追蹤管理
將當(dāng)前所在目錄初始化成git倉庫:
git init
此時目錄下會多出一個.git文件
配置name和email
使用git config
進(jìn)行配置
git config user.name "用戶名"
git config user.email "郵箱地址"
這兩個配置項必須與git遠(yuǎn)程倉庫對應(yīng)
查看配置項
git config -l
刪除配置
git config --unset user.name
git config --unset user.email
使用--global
選項選項,將配置應(yīng)用于本地的所有g(shù)it倉庫:
git config --global user.name "用戶名"
git config --global user.email "郵箱地址"
相應(yīng)的,要刪除全局的配置,只需要在刪除命令中加上--global
選項
.git目錄的結(jié)構(gòu)
查看一下git的目錄樹
我們不能修改.git下的所有文件,也不能更改.git的目錄結(jié)構(gòu),這將導(dǎo)致git出錯
在.git所在目錄下創(chuàng)建了文件,文件會受到git的版本控制嗎?
解釋之前先說明兩個概念:
- 版本庫(即倉庫):當(dāng)前目錄下的.git被稱為版本庫
- 除了.git之外的其他文件被稱為工作區(qū)。我們只能修改工作區(qū)中的內(nèi)容,不能修改版本庫中的內(nèi)容
工作區(qū)與版本庫的關(guān)系:
版本庫中,stage被稱為暫存區(qū),也叫索引index。此外還有一個master分支,由HEAD
指針指向
工作區(qū)中的修改(新增、修改、刪除)不會受到git的追蹤
執(zhí)行add命令后,git會將工作區(qū)中的修改寫入暫存區(qū)
執(zhí)行commit后,git會將暫存區(qū)中的修改提交到master分支中,此時修改真正地被寫入版本庫,這些修改才會受到git的追蹤控制
此外,版本庫中還有一個分區(qū):objects對象庫。對象庫中存在多個對象,所有對工作區(qū)的修改都會被寫入到這些對象中(這些對象保存了工作區(qū)的修改)
可以注意到暫存區(qū)和master都是目錄樹的結(jié)構(gòu),其中存儲了文件,而這些文件中存儲了對象庫中對象的指針。也就是說,暫存區(qū)和master通過保存對象庫中的對象指針,以表示當(dāng)前的狀態(tài)
執(zhí)行add將修改暫存區(qū)的目錄樹,使之索引到對象庫中的對象
執(zhí)行commit操也修改master的目錄樹,使之索引到對象庫中的對象
git add & git commit
將工作區(qū)中的修改寫入暫存區(qū)中
git add filename [filename]
可以使用git add .
,表示將當(dāng)前目錄下的所有修改寫入暫存區(qū)中
將暫存區(qū)中的修改寫入master分支(本地倉庫)中
git commit -m "描述此次提交的目的"
使用git commit
時,需要帶上-m
選項并輸入此次提交的目的
如果直接輸入git commit
,我們將進(jìn)入vim編輯器并輸入此次提交的目的。顯然直接使用-m
選項是更方便的
打印時間從近到遠(yuǎn)的commit記錄,記錄包含了每次提交的提交目的
git log
其中commit id是經(jīng)過hash得到的定長字符串。對于git log
命令,攜帶--pretty=oneline
選項,將簡化打印的內(nèi)容為一行
.git目錄結(jié)構(gòu)的變化
再創(chuàng)建兩個文件,將其commit到倉庫中
此時觀察.git的目錄結(jié)構(gòu)
其中新增了index文件,即暫存區(qū)。執(zhí)行add操作后,暫存區(qū)保存了工作區(qū)的修改,所以此時出現(xiàn)了index文件
此外還有存在一個HEAD文件
cat一下HEAD文件,發(fā)現(xiàn)指向了倉庫中的master文件,也cat一下master文件
發(fā)現(xiàn)master文件保存了commit id,該commit id為最近一次commit操作的id
首先,master和index中保存著對象指針,指針指向的對象存儲了工作區(qū)中的修改信息
所以commit id是一個指針,前兩位為目錄名,剩下的數(shù)字為文件名,這些文件存儲在.git的objects目錄下,可以在objects目錄中找到對應(yīng)文件
使用命令,打印object的信息
git cat-file -p commit id
-p
選項可以將打印信息簡化
(似乎不使用-p
還無法打印信息)
可以看到object中記錄了執(zhí)行commit操作的用戶名與郵箱,以及上一次的commit id
第一行還有一串commit id,git cat-file下,看看是什么
可以看到,該對象似乎保存了工作區(qū)中每個文件的object指針,每個文件對應(yīng)的object中保存了文件的修改信息
ReadMe文件中,確實只有"hello git"這串字符串
總結(jié)一下,object保存了每次的commit信息,以及工作區(qū)中每個文件的修改信息。如何獲取object的指針?master文件保存了最近一次commit對應(yīng)的object指針,也保存了上一次commit的object指針
注意:要想將工作區(qū)中的修改提交到版本庫中,必須先執(zhí)行add將修改提交到工作區(qū),再執(zhí)行commit將修改提交到版本庫,這兩個操作不能顛倒
git追蹤管理的數(shù)據(jù)
git追蹤管理的不是文件,而是每一次的修改
修改ReadMe文件,使用git status
命令查看當(dāng)前倉庫的狀態(tài)
打印信息說,我們修改了ReadMe文件,但是暫存區(qū)中沒有文件(no changes added)需要被提交
因為我們沒有執(zhí)行add
使用以下命令,查看工作區(qū)與暫存區(qū)中[某個文件]的差異
git diff [filename]
打印的是unix通用的diff格式:
---
和a
表示改動前,+++
和b
表示改動后
-1表示第一行為改動前的內(nèi)容,+1表示之后的一行為改動后的內(nèi)容,2表示改動后的內(nèi)容到第二行結(jié)束
使用以下命令,查看版本庫與工作區(qū)中[某個文件]的差異
git diff HEAD [filename]
將當(dāng)前工作區(qū)的修改add到暫存區(qū)中,執(zhí)行git status
打印信息說,當(dāng)前暫存區(qū)中的信息已經(jīng)準(zhǔn)備好被提交了(changes to be committed)
并且指明了暫存區(qū)中修改的文件為ReadMe
commit之后,再執(zhí)行commit status
打印信息說,工作區(qū)與暫存區(qū)都沒有發(fā)生修改
git的版本回退
版本回退本質(zhì)上是回退版本庫中的內(nèi)容
使用以下命令,進(jìn)行版本回退
git reset [--soft | --mixed | --hard] [HEAD] -- commit id
- –soft:回退版本庫中的內(nèi)容
- –mixed:回退版本庫與暫存區(qū)中的內(nèi)容,可以指定需要回退的文件
- –hard:回退所有區(qū)域的內(nèi)容
其中miexed為默認(rèn)選項
之前說過,執(zhí)行了git init
后的目錄下有三個區(qū)域,工作區(qū)、暫存區(qū)以及版本庫(倉庫),reset命令的不同選項將不同程度地回退這些區(qū)域中的內(nèi)容
注意:hard選項需要慎用!因為它將回退工作區(qū)中的數(shù)據(jù)!
根據(jù)git log
打印的commit id,進(jìn)行hard選項的版本回退,使ReadMe中只有"hello git"
可以看到之前有的"appending…“消失,只剩下"hello git”,并且日志也進(jìn)行了回退
如果你有回退之前的commit id,你甚至可以撤銷回退,回退之前的回退
該commit id為回退之前的id,此時成功撤銷了回退
同時日志的回退也被撤銷了
如果想要撤銷回退,執(zhí)行git reflog
可以查看所有add和commit的信息,其中就包含了commit id的前7個字符,使用commit id的前7個字符也能進(jìn)行執(zhí)行/撤銷回退
而一旦找不到commit id,將無法執(zhí)行/撤銷回退的操作
回退的原理
為什么git的回退這么快?因為回退只是修改了master保存的指針
master存儲了最近一次的commit id,也就是object指針。object對象記錄了每一次的修改操作。版本回退本質(zhì)上是在修改master的值,使master指向不同的object指針。此時倉庫中最近一次的commit操作就被修改,最近一次的commit不同,倉庫中的數(shù)據(jù)就不同
回退的三種情況
撤銷操作的本質(zhì):防止錯誤的代碼從版本庫中被push到遠(yuǎn)程倉庫中
用code表示錯誤的代碼,那么將出現(xiàn)以下三種情況
工作區(qū) | 暫存區(qū) | 版本庫 | 解決方法 |
---|---|---|---|
code | git checkout – | ||
code | code | git reset + git checkout --或者git reset --hard | |
code | code | code | git reset --hard,前提條件: commit之后沒有push |
- 工作區(qū)中開發(fā)了大量代碼,但是沒有add,此時要撤銷工作區(qū)中的修改
- 工作區(qū)中開發(fā)了大量代碼,add了但是沒有commit,此時要撤銷工作區(qū)與暫存區(qū)的修改
- 工作區(qū)中開發(fā)了大量代碼,add并且commit了,此時要撤銷工作區(qū)、暫存區(qū)與版本庫的修改
情況一:只有工作區(qū)需要回退代碼
執(zhí)行命令,將工作區(qū)的文件回退到最近一次add的狀態(tài),也就是和暫存區(qū)一致
git checkout -- filename
注意,必須要加上--
,否則命令的效果完全不一樣!
情況二:工作區(qū)和暫存區(qū)都需要回退代碼
先修改ReadMe中的內(nèi)容,添加"code"并且add修改到暫存區(qū)中
兩種解決方法:
執(zhí)行hard回退命令,使工作區(qū)與暫存區(qū)中的代碼和版本庫一致
git reset --hard HEAD filename
注意,git reset --hard
不能回退指定文件,只有mixed
模式能回退指定文件!
另一種方法:將情況二轉(zhuǎn)換成情況一
執(zhí)行命令,使暫存區(qū)中的代碼回退,與版本庫中的代碼一致
git reset HEAD filename
HEAD
指針指向了master分支,而master分支保存版本庫的最近一次修改,即最新版本
所以git reset HEAD
將使版本庫和暫存區(qū)回退到當(dāng)前版本,而版本庫本來就是當(dāng)前版本,所以只有暫存區(qū)回退到了當(dāng)前版本
用git status
驗證:
此時git status
說,暫存區(qū)中沒有修改需要被提交,也就是暫存區(qū)的內(nèi)容和工作區(qū)中的內(nèi)容一致
此時執(zhí)行git checkout -- ReadMe
,使工作區(qū)中版本和暫存區(qū)中的版本一致即可
情況三:所有區(qū)域都需要回退代碼
執(zhí)行命令,將工作區(qū)、暫存區(qū)以及版本庫中的代碼回退到上一版本
git reset --hard HEAD^
(其中HEAD
,表示上一次修改即當(dāng)前版本,而HEAD^
表示上一個版本,HEAD^^
表示上兩個版本…)
一般來說都是將代碼回退到上一版本,但是具體來說是哪個版本,就需要根據(jù)情況決定了
版本庫中文件的刪除
第一種方式:
- 先刪除工作區(qū)中的文件
- 再將修改提交到暫存區(qū)中
- 最后將暫存區(qū)中的修改提交到版本庫中
rm file1
git add file1
git commit -m "delete file1"
可以看到當(dāng)前版本庫中已經(jīng)沒有file1文件了
第二種方式:
- 執(zhí)行g(shù)it rm,同時刪除工作區(qū)與暫存區(qū)中對應(yīng)文件
- 將暫存區(qū)中的修改commit到版本庫中
其實就是git rm
等價于rm+git add
git rm file2
git commit -m "delete file2"
可以看到當(dāng)前目錄只剩下了ReadMe文件
git分支管理
之前說過,HEAD
指針指向master分支,master分支存儲了一個對象指針,該對象保存了最近一次commit,查看該對象的數(shù)據(jù)
可以看到該對象中還保存了一個對象指針parent
,分支下的每一次commit都有先后時間,根據(jù)時間順序,保存每次修改的對象就形成了一條時間鏈。parent
保存了時間鏈中,當(dāng)前對象的上一個對象的指針
通過parent
指針,我們就能不斷地往前追溯歷史commit
我們還可以在master主分支上創(chuàng)建分支,并對該分支提交修改,此時也將形成一條版本鏈
執(zhí)行指令,查看當(dāng)前git倉庫中存在哪些分支
git branch -a
-a
將顯示本地分支與遠(yuǎn)程分支,默認(rèn)只顯示本地分支
除了master分支,HEAD
也能指向其他分支,由HEAD
指向的分支被稱為工作分支,也就是當(dāng)前分支
執(zhí)行命令,創(chuàng)建新的分支:
git brach dev
創(chuàng)建新的分支后的目錄結(jié)構(gòu):
此時.git目錄下出現(xiàn)了dev文件,查看該文件中的內(nèi)容
發(fā)現(xiàn)它和master文件的內(nèi)容一樣,由此證明新建分支的數(shù)據(jù)基于原分支
切換分支
git checkout 分支名
* 在dev之前,說明當(dāng)前HEAD
指針指向了dev分支
也能使用一行命令完成分支的創(chuàng)建與切換:
git ckeckout -b 分支名
在dev分支中,修改ReadMe文件,并切換到master分支,查看ReadMe文件
發(fā)現(xiàn)只有在dev分支中才能看見修改后的ReadMe文件,而在master分支中,無法看見修改后的ReadMe文件
說明此次的修改被提交到了dev分支上,對master分支不可見
同理,在dev分支上提交數(shù)據(jù)后,refs/heads/dev保存的對象指針和refs/heads/master保存的對象指針不再相同
如何合并分支?首先要切回master分支
git checkout master
git merge 分支名
合并分支后,打印信息說,master分支下的ReadMe文件新增了一行數(shù)據(jù)
分支的刪除
不能刪除當(dāng)前所在分支(工作分支),只能刪除其他的分支
git branch -d 分支名
合并分支與刪除分支的速度非常快。因此,git鼓勵我們在分支上完成任務(wù),合并到master分支中再刪除分支,這樣將更加安全
如果分支執(zhí)行了add或者commit,但是沒有被合并,此時無法使用-d
刪除該分支(git認(rèn)為創(chuàng)建出來的分支都是要被merge的,只有在merge分支后,才能刪除該分支),只能使用-D
強制刪除該分支
git branch -D 分支名
合并分支時的沖突
在dev分支中修改ReadMe文件,也在master分支中修改ReadMe文件,使兩份文件不同
修改完文件我們要進(jìn)行add和commit,使倉庫中兩個分支下的文件內(nèi)容不同
此時執(zhí)行合并操作
打印信息說合并失敗,此時查看ReadMe文件
其中<<<<<<HEAD
到=======
之間為當(dāng)前分支下的數(shù)據(jù),========
到dev之間為dev分支的數(shù)據(jù),兩者不相同所以產(chǎn)生了沖突
如何解決沖突?手動解決,在master分支中的沖突文件中保留想要的代碼。解決沖突后執(zhí)行add和commit,此時合并操作才算完成
查看當(dāng)前日志
使用以下命令,可以以圖表的形式看到master分支與dev分支之間的關(guān)系
git log --graph --abbrev-commit
分支的合并模式
如果執(zhí)行命令
git merge 分支名
調(diào)試信息中有"fast-forward"字段時,說明這次的提交為ff模式
該模式的合并無法通過git log --graph --abbrev-commit
查看,圖中不會出現(xiàn)兩個分支合并成一個分支的信息,因此我們無法得知master合并了哪個分支
ff模式的本質(zhì)是將被合并分支的最近一次提交對象指針寫入到master分支的最近一次提交對象指針中
當(dāng)合并沒有發(fā)生沖突時,git默認(rèn)使用ff模式
此外,還有一種模式: no-ff,這種模式的合并可以通過git log --graph --abbrev-commit
知道兩哪個分支發(fā)生了合并
使用no-ff模式的合并:
git merge -no-ff -m "此次合并的目的" 被合并的分支名
由于合并完分支后,還需要進(jìn)行commit操作,所以需要-m
提交信息
分支策略
master主分支對應(yīng)著線上環(huán)境,必須是十分穩(wěn)定的,所以提交的代碼需要能穩(wěn)定運行,沒有重大的bug
而其他分支則是不穩(wěn)定,存在bug的。開發(fā)人員在這些分支上進(jìn)行開發(fā),進(jìn)行一系列測試驗證后,就能將其他分支上的代碼合并到master分支中
基于分支,我們就能進(jìn)行同一項目的多人同時開發(fā),同時也演變出了多種分支策略
git stash
如果在其他分支中修改了文件,未進(jìn)行add和commit,此時的操作將不受到git的版本控制,只是單純的對工作區(qū)的修改。切回master分支后,可以在本地看見其他分支對文件的修改
若其他分支修改文件后,進(jìn)行了add和commit,此時的操作將受到git的版本控制。切回master分支后,無法看見其他分支對文件的修改
如果不進(jìn)行add和commit,又不想讓master分支看見其他分支對文件的修改,可以使用命令
git stash
該命令將保存分支對文件的修改到一個特殊文件中,也就是將修改后的文件添加到git的版本控制中,此時master分支無法看見其他分支對于文件的修改
此時.git的目錄樹中,多了一個stash文件,用來保存分支中的修改
執(zhí)行命令,打印stash中保存的修改
git stash list
如果在dev分支中修改了文件,并執(zhí)行git stash
,切出該分支,再切回dev分支
此時分支中的數(shù)據(jù)和master分支相同,要想恢復(fù)之前所做的修改,就需要執(zhí)行命令,將stash中的修改恢復(fù)到分支中
git stash pop
不要在master分支上解決沖突
項目上線后可能遇到的場景:存在一個小bug,此時基于master分支創(chuàng)建分支fix_bug
進(jìn)行bug修復(fù),修復(fù)成功后在master分支中合并fix_bug分支,項目再次上線
同時,項目的開發(fā)也在不斷進(jìn)行中,在發(fā)現(xiàn)bug之前,創(chuàng)建了一個分支dev開發(fā)新的功能。等到功能開發(fā)好時,項目已經(jīng)不再是當(dāng)時創(chuàng)建分支時的項目,而是修改了bug后的項目。此時在master分支中合并dev分支將產(chǎn)生沖突
我們不能直接合并dev分支,并在master分支上手動修改文件,這可能導(dǎo)致使修改后的文件出現(xiàn)bug
正確做法應(yīng)該是:在dev分支上合并master分支并且手動修改沖突,測試沒有問題后,再到master分支中合并dev分支
git的遠(yuǎn)程操作
git的全程叫做分布式版本控制系統(tǒng),版本控制很好理解,如何理解分布式?
一個項目的開發(fā)往往需要多人的分工協(xié)作,之前所說的git倉庫:工作區(qū)、暫存區(qū)以及版本庫都是在本地運行的。一個開發(fā)人員對項目進(jìn)行了修改,另一個開發(fā)人員要如何獲取到他的修改呢?或者說如何讓其他人看到我對項目的修改?
顯然只使用本地的git無法解決這個問題。git為我們提供了一個解決方案,使用中央服務(wù)器存儲git倉庫,我們也叫它遠(yuǎn)程倉庫
每個開發(fā)人員都能訪問到遠(yuǎn)程倉庫,需要開發(fā)項目時,從遠(yuǎn)端倉庫將整個倉庫拉取下來進(jìn)行開發(fā)。開發(fā)完成后,將本地的修改提交到遠(yuǎn)程倉庫中。那么其他開發(fā)人員就能通過遠(yuǎn)程倉庫看到你對項目的開發(fā),并且也能拉取你對項目的修改,進(jìn)一步進(jìn)行開發(fā)
用https克隆遠(yuǎn)程倉庫,注意:不能在擁有.git目錄的路徑下(已經(jīng)初始化過本地倉庫的地方)克隆倉庫!
克隆也能理解為第一次拉取
在遠(yuǎn)程倉庫中可以找到該倉庫的鏈接,通常有https和ssh協(xié)議,先演示https協(xié)議的克隆,將URL復(fù)制下來,執(zhí)行命令
git clone URL
查看遠(yuǎn)程倉庫的信息
git remote [-v]
直接使用git remote
將打印本地倉庫中已經(jīng)配置的遠(yuǎn)程倉庫名字,通常是origin
而git remote -v
將查看已經(jīng)配置的遠(yuǎn)程倉庫列表,以及它們的URL。fetch
表示本地?fù)碛羞h(yuǎn)程倉庫的拉取權(quán)限,push
則表示提交權(quán)限
用ssh克隆遠(yuǎn)程倉庫:
需要先將本地服務(wù)器的公鑰放到遠(yuǎn)端的git服務(wù)器中
如何配置git服務(wù)器的公鑰?
找到個人設(shè)置中的相關(guān)配置項
點擊添加公鑰:
在本地服務(wù)器中生成公鑰與私鑰:
進(jìn)入/~/.ssh目錄,如果沒有則創(chuàng)建目錄
如果目錄中沒有id_rsa 和id_rsa.pub文件,則執(zhí)行以下命令
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
其中-C
選項表示添加注釋信息,用來表示生成的密鑰對的用途,將這個信息設(shè)置為自己的郵箱即可
輸入命令后一直回車直到能夠輸入其他命令為止
此時目錄下新增兩個文件:id_rsa 和id_rsa.pub
生成后,將公鑰(id_rsa.pub中的字符)寫入git服務(wù)器中
此時執(zhí)行命令,即可克隆倉庫
git clone ssh鏈接
將修改提交到遠(yuǎn)程倉庫
注意:不是將整個本地倉庫的修改提交到遠(yuǎn)程倉庫,而是將某個分支的修改提交到遠(yuǎn)程倉庫
克隆完遠(yuǎn)程倉庫后,需要配置user.name和user.email,這兩個信息要和git服務(wù)器中的信息一致
首先在工作區(qū)中修改文件,并add與commit,最后執(zhí)行push,將版本庫中的修改提交到遠(yuǎn)程倉庫
git push 倉庫名 本地倉庫的分支:遠(yuǎn)程倉庫的分支
push其實做了兩步操作:將本地倉庫某個分支的修改提交到遠(yuǎn)程倉庫中,將指定分支與遠(yuǎn)端分支進(jìn)行合并
其中,倉庫名是本地服務(wù)器配置的遠(yuǎn)程倉庫的名字,一般是origin
同時指定要push哪個本地分支中的修改到遠(yuǎn)程倉庫中的哪個分支,這兩個分支名一般用:
隔開,當(dāng)兩者相同時,可以只寫一次分支名(github的master分支現(xiàn)在叫做main分支)
此時遠(yuǎn)程倉庫中出現(xiàn)了分支的修改,新增了ReadMe文件
push操作的本質(zhì)是本地分支與遠(yuǎn)端分支的交互,交互之前需要先建立連接。一般在克隆倉庫時,本地倉庫的master分支與遠(yuǎn)程倉庫的master分支就自動建立了連接,可以直接使用git push
。而其他分支沒有建立連接,需要使用上面的長命令進(jìn)行push
操作
當(dāng)本地倉庫的版本領(lǐng)先于遠(yuǎn)程倉庫的版本,此時進(jìn)行push操作以推送更新
當(dāng)遠(yuǎn)程倉庫的版本領(lǐng)先于本地倉庫的版本,此時要進(jìn)行pull操作以同步與遠(yuǎn)程倉庫的版本
假設(shè)遠(yuǎn)程倉庫的hello.txt被其他人修改了并且push了,這是修改后的內(nèi)容
此時我要進(jìn)行下一步的開發(fā),就必須與遠(yuǎn)程倉庫的版本保持同步
使用pull命令完成同步
git pull 倉庫名 本地倉庫的分支:遠(yuǎn)程倉庫的分支
pull和push的使用相同,pull其實也進(jìn)行了兩步操作:將遠(yuǎn)程倉庫中指定分支的修改拉取到本地,與本地分支進(jìn)行合并
push時忽略特殊文件
創(chuàng)建遠(yuǎn)程倉庫中,可以勾選添加.gitignore文件的選項:指定一些不想被push的文件,這些文件的修改就不會被add到暫存區(qū)中,更不會被push到遠(yuǎn)程倉庫中了
在.gitignore文件中的文件不會被git追蹤管理,即忽略這些文件,.gitignore文件需要位于git工作區(qū)的根目錄下
若新建倉庫時沒有勾選添加.gitignore文件的選項,后續(xù)想要添加該文件時,可以直接添加
該文件在工作區(qū)的根目錄下
此時創(chuàng)建一個以so結(jié)尾的文件,并將當(dāng)前目錄下的所有文件add到工作區(qū)中,執(zhí)行git status
命令,查看哪些文件的修改需要被commit到版本庫中
發(fā)現(xiàn)調(diào)試信息中,沒有a.so
文件只有.gitignore
文件,說明.gitignore
文件生效了
如何強制添加文件到暫存區(qū)中,就算該文件在.gitignore中出現(xiàn)?
為add添加-f
選項,強制提交修改到暫存區(qū)中
git add -f filename
也可以在.gitignore
文件中添加規(guī)則,使git不要不略某個文件的提交
!
表示不忽略該文件的提交
如何判定某一文件是否被忽略?
git check-ignore -v filename
打印信息說,該文件被第三行的規(guī)則忽略了
配置命令的別名
git config --global alias.別名 '原名(不需要加git)'
給status起別名
git的標(biāo)簽管理
使用標(biāo)簽可以方便的查看信息,以及記錄一些有意義的信息
執(zhí)行命令,為最近的一次commit將被打上指定的標(biāo)簽
git tag 標(biāo)簽名
查看所有標(biāo)簽
git tag
.git的目錄樹中也出現(xiàn)了相應(yīng)的目錄,查看該文件
發(fā)現(xiàn)該文件存儲了最近一次的commit id
為指定的commit打標(biāo)簽,先通過git log --pretty=oneline --abbrev-commit
,列出所有commit id,找到想要打標(biāo)簽的commit id
執(zhí)行
git tag 標(biāo)簽名 commitid
執(zhí)行命令,為commit打標(biāo)簽并添加注釋:
git tag -a 標(biāo)簽名 -m "注釋內(nèi)容" commit id
執(zhí)行命令,查看標(biāo)簽的注釋:
git show 標(biāo)簽名
git show
將顯示對應(yīng)commit的詳細(xì)信息,如果該commit的標(biāo)簽有注釋,那么也將一起展示,如果沒有則只顯示其他信息
刪除標(biāo)簽:
git tag -d 標(biāo)簽名
推送標(biāo)簽
git push 倉庫名 標(biāo)簽名
推送所有標(biāo)簽:
git push 倉庫名 --tags
刪除遠(yuǎn)端倉庫的標(biāo)簽(首先要先刪除本地倉庫的標(biāo)簽)
git push 倉庫名 :標(biāo)簽名
git實戰(zhàn)
同一分支下的多人協(xié)作(不推薦)
開發(fā)者1在dev分支下的hello.txt
文件中添加"111",開發(fā)者2在dev分支下的test文件中添加"222"
先在遠(yuǎn)端倉庫中添加新的分支
接著在兩個開發(fā)者的機器上執(zhí)行git pull
,獲取最新的倉庫版本(新的分支)
但是執(zhí)行git branch
后,無法看到新的分支。這是因為遠(yuǎn)端的分支與本地的分支沒有關(guān)系,所以就算拉取了,也不會執(zhí)行分支合并的操作。使用git branch -r
選項就能看到遠(yuǎn)端的分支
此時我們要在本地手動創(chuàng)建名字相同的分支,并將本地分支與遠(yuǎn)端分支建立連接
執(zhí)行命令建立連接
git checkout -b 本地分支名 倉庫名/遠(yuǎn)端分支名
除此之外,使用其他命令也能達(dá)到同樣效果(前提是dev分支不存在)
git branch 本地分支名 倉庫名/遠(yuǎn)端分支名v
git checkout 本地分支名
若dev分支存在,則執(zhí)行
git branch --set-upstream-to=倉庫名/遠(yuǎn)端分支名 本地分支名
git checkout 本地分支名
執(zhí)行git branch -vv
可以查看本地倉庫與遠(yuǎn)端倉庫的連接
為什么要建立連接?這樣可以直接使用git push
與git pull
這樣的短命令,而不使用git push origin main
這樣的長命令
開發(fā)者1完成操作,修改文件后add、commit、push三板斧
開發(fā)者2執(zhí)行相同的操作
而開發(fā)者2修改完hello.txt卻無法提交,原因是此時的遠(yuǎn)端倉庫中hello.txt和開發(fā)者2本地倉庫最近一次pull的版本不同(開發(fā)者1的提交導(dǎo)致版本的不同),此時提交將產(chǎn)生沖突
解決方法是:執(zhí)行git pull
,此時hello.txt
文件產(chǎn)生沖突,手動修改沖突并重新add、commit、push即可
最后一步:將dev分支合并到master分支中
有兩種方法:
- 將本地的dev分支合并到master分支中,再將master分支push到遠(yuǎn)端
- 在git服務(wù)器上提交pr(pull request)申請,由管理員審批后,合并將被執(zhí)行
如何提交pr申請?
選擇選項,將dev分支合并到main分支中,添加標(biāo)題和內(nèi)容后選擇reviewers和addignees,點擊新建pr
關(guān)于reviewers和addignees的區(qū)別,可以看這篇博客Git GitHub上的Reviewers和Assignees之間有什么區(qū)別|極客筆記 (deepinout.com)
相關(guān)人員審查沒問題后,就會進(jìn)行合并操作了
另一種方法是在本地執(zhí)行merge操作,推薦使用pr合并方式,經(jīng)過審查員的審查,合并操作會更加安全
首先,執(zhí)行合并操作的開發(fā)人員的本地倉庫中,dev分支可能不是最新,此時需要先pull拉取最新版本
git checkout dev
git pull
由于無法保證main分支也是最新的,所以也需要pull
git checkout main
git pull
由于無法保證將dev分支合并到main分支是否會發(fā)生沖突,所以先到dev分支下,將main分支合并到dev分支。若發(fā)生沖突則手動解決沖突
git checkout dev
git merge main
解決完沖突后,再回到main分支下,合并dev分支
git checkout main
git merge dev
最后進(jìn)行push操作即可
git push
刪除dev分支(可選)
git branch -d dev
可以看到同一分支下的多人協(xié)作非常麻煩,產(chǎn)生沖突的概率極大,需要不停的pull解決沖突
所以開發(fā)中的多人協(xié)作一般是在不同分支下進(jìn)行的
不同分支下的多人協(xié)作
每個開發(fā)者(開發(fā)項目的不同功能)對應(yīng)不同分支,在屬于自己的分支上提交自己開發(fā)的代碼
最后這些代碼將合并到main分支下
如:開發(fā)者1在feature-1分支下提交file1文件,開發(fā)者2在feature-2分支下提交file2文件
開發(fā)者1:首先pull更新本地的master分支,然后在本地master分支下,創(chuàng)建feature-1分支,編輯文件file1并進(jìn)行add和commit操作
git pull
git checkout -b feature-1
此時的push操作比較特殊,不能直接git push
,而要執(zhí)行
git push 遠(yuǎn)端倉庫名 本地分支名
因為此時的遠(yuǎn)端倉庫中沒有feature-1分支,我們只是在本地創(chuàng)建了feature-1分支,所以這次的提交需要將整個分支進(jìn)行提交
總結(jié)下:可以在本地創(chuàng)建新分支,也可以在遠(yuǎn)端創(chuàng)建新分支
- 在本地創(chuàng)建新分支后,需要將整個分支進(jìn)行提交
- 而在遠(yuǎn)端創(chuàng)建新分支后,需要先pull獲取遠(yuǎn)端的分支,再創(chuàng)建本地的同名分支并建立連接
此時遠(yuǎn)程倉庫下已經(jīng)存在feature-1分支了
開發(fā)者2執(zhí)行與開發(fā)者1相同的操作:基于master分支創(chuàng)建新的分支feature-2,在該分支上編寫文件file2,并執(zhí)行add、commit以及push操作,在執(zhí)行push操作之前需要先pull獲取最新的遠(yuǎn)程倉庫
開發(fā)過程中可能遇到的場景:開發(fā)者1需要幫助開發(fā)者2完成后續(xù)開發(fā)
此時開發(fā)者1的本地倉庫中沒有featrue-2分支,所以需要將該分支拉取下來
解釋一下這時的pull為什么只需要使用短鏈接?
pull操作其實有兩種:1. 拉取某一分支下的內(nèi)容,此時需要使用長連接,如果本地分支與遠(yuǎn)端分支建立連接后即可使用短連接 2. 拉取倉庫中的內(nèi)容,如新的分支,此時使用短連接即可,但是拉取到的新分支不會和本地分支建立連接
但是拉取操作只是將遠(yuǎn)端的分支拉取下來,本地沒有相應(yīng)的分支,打印的信息提示我們要在本地創(chuàng)建相同的分支并與其鏈接
git checkout -b feature-2 origin/feature-2
此時處于feature-2分支下,繼續(xù)編寫該分支下的文件,完成開發(fā)者2未完成的代碼
最后:將feature-1分支和feature-2分支合并到main分支下
在git服務(wù)端分別提交兩次pr申請即可
在提交pr申請前,推薦先用其他分支合并main分支,解決可能存在的沖突,再用main分支合并其他分支,此時將不會產(chǎn)生沖突
為什么本地依然能看到遠(yuǎn)端已經(jīng)刪除的分支?
將遠(yuǎn)端分支刪除后,本地使用git branch -a
依然能看到遠(yuǎn)端分支,如何解決?
使用命令清理遠(yuǎn)端無用分支即可
git remote prune origin
此時遠(yuǎn)端分支只有main分支,剩下的本地分支用git branch -d
刪除即可
git flow模型
git flow模型是企業(yè)級常用的一種git分支設(shè)置規(guī)范,這只是一種常用的開發(fā)模型,并不適合于所有的開發(fā)團(tuán)隊。了解它有助于我們理解軟件開發(fā)的流程
分支 | 名稱 | 適用環(huán)境 |
---|---|---|
master | 主分支 | 生產(chǎn)環(huán)境 |
release | 預(yù)發(fā)布分支 | 預(yù)發(fā)布/測試環(huán)境 |
develop | 開發(fā)分支 | 開發(fā)環(huán)境 |
feature | 需求開發(fā)分支 | 本地 |
hotfix | 緊急修復(fù)分支 | 本地 |
master分支 |
- master為主分支,該分支唯一且只讀,用于部署正式發(fā)布環(huán)境,一般由合并release分支得到
- master分支為穩(wěn)定的代碼庫,任何時候都不能直接在master分支上修改代碼
- 產(chǎn)品的功能全部實現(xiàn)后,最終在master分支上對外發(fā)布。并且master分支上的所有提交都應(yīng)該打標(biāo)簽(tag)做記錄,方便追溯
- master分支不可刪除
feature分支
- feature為新功能或新特性的開發(fā)分支,以develop分支為基礎(chǔ)創(chuàng)建feature分支
- 命名通常為
feature/user_createtime_feature
,表示開發(fā)人員,開發(fā)時間以及所開發(fā)的特性 - 新特性開發(fā)完成后需要將feature分支合并到develop分支中,且刪除feature分支
develop分支
- develop為開發(fā)分支,基于master分支創(chuàng)建的唯一且只讀分支,始終保持最新完成以及bug修復(fù)后的代碼??刹渴鸬綄?yīng)開發(fā)集群
- 通常用來合并feature分支,也可直接在develop分支上開發(fā)
release分支
- release分支為預(yù)發(fā)布分支,基于develop分支創(chuàng)建,可以部署到測試或者預(yù)發(fā)布集群
- 通常的命名規(guī)則:
release/version_publishtime
,表示發(fā)布的版本以及發(fā)布時間 - release分支通常用于提交給測試人員進(jìn)行測試,若出現(xiàn)問題則需要驗證develop是否出現(xiàn)問題,測試完成后可以刪除release分支
hotfix分支
- hotfix為bug修復(fù)分支或補丁分支,主要用于線上版本的bug修復(fù)
- 命名規(guī)則通常為
hotfix/user_createtime_hotfix
,表示相關(guān)人員,創(chuàng)建時間以及具體的bug - 問題修復(fù)完成,將其合并到master分支后刪除