Git 的原理與使用(中)

Git 的原理與使用(上)中介紹了Git初識,Git的安裝與初始化以及工作區、暫存區、版本庫相關的概念與操作,本文接著上篇的內容,繼續深入介紹Git在的分支管理遠程操作方面的應用。

目錄

五、分支管理

1.理解分支

2.創建分支 branch?

3.切換分支

4.合并分支

5.創建、切換、合并分支流程圖

6.刪除分支?

7.合并沖突

補充:查看分支合并的情況

8.分支管理策略

Fast Forward 模式(ff模式)

非Fast Forward模式(no-ff模式)

9.分支策略

10.bug分支

疑問解決

11.刪除臨時分支

12.分支小結

六、遠程操作

1.理解分布式版本控制系統

2.遠程倉庫

新建遠程倉庫

Issues

Pull Request

克隆遠程倉庫

HTTPS協議克隆

SSH協議克隆

向遠程倉庫推送 push

拉取遠程倉庫

3.配置Git

忽略特殊文件

給命令配置別名

**小結

**下篇內容


五、分支管理

1.理解分支

分支是Git的殺手級功能之一。

它就像是科幻電影里面的平行宇宙,當你正在電腦前努力學習C++的時候,也許另一個平行宇宙里的另一個你正在努力學習JAVA。這兩個平行宇宙互不干擾,而在某個時間點,它倆發生了合并——于是,你既精通了C++,又精通了JAVA!

版本回退章節里我們已經知道,Git會把每次提交串成一條時間線,這條時間線就可以理解為是一個分支。截止到目前我們的Git倉庫里中只有一條時間線,這個分支叫主分支,即master分支(也叫main分支)

然后再來理解一下HEAD。HEAD嚴格來說指向的不是“提交(commit)”,而是當前所在的分支,而分支才是指向“提交(commit)”的。比如當前我們所在的分支是master,那么HEAD指向的就是master,master指向的才是“提交”。如下圖所示:

每次執行commit操作,master分支都會向前移動一步以指向最新的“提交”。這樣,隨著你不斷commit,master分支的線也會越來越長。而HEAD則一直指向指向當前分支不變,即現在我們所在的master分支。

可以通過

git cat-file -p <commit ID>

命令來查看提交信息:

2.創建分支 branch?

如何查看當前本地倉庫中已有的所有分支?

在工作目錄下執行

git branch

命令,系統就能為我們打印出當前本地倉庫中有哪些分支:

hyb@139-159-150-152:~/gitcode$ git branch #查看當前本地所有分支
* master    # 顯示結果

這里查詢到當前本地倉庫中只有一個master主分支。

在我們創建本地倉庫時,git會自動給我們創建出一個master主分支。master前面有一個? *? ,*master?既表示master是當前的工作分支,也表示master分支正在被HEAD指針所指向。

關于HEAD:

  1. HEAD不僅可以指向master主分支,也可以指向其它任意分支。

  2. 被HEAD指向的分支是當前正在工作的分支。由于之前我們的HEAD一直指向的是master分支,因此add操作、commit操作都是在master主分支上完成的。

為了演示多分支的情況,這里我們來創建第一個新的分支dev,對應的命令為:

git branch <分支名>
hyb@139-159-150-152:~/gitcode$ git branch dev #新建分支dev
hyb@139-159-150-152:~/gitcode$ git branchdev
* master

當我們創建新的分支后,Git 便新建了一個指針叫 dev。而?*HEAD 表示當前的 HEAD 仍然指向?master 分支,并沒有發生變化。

也就是說,單純的創建分支,是不會自動切換分支的。?

# 打印一下HEAD指針的內容,可見HEAD指向的還是master
hyb@139-159-150-152:~/gitcode$ cat .git/HEAD
ref: refs/heads/master

此時,cat一下dev和master的內容,會發現它們兩個指向的是同一個修改(即commit Id),這是因為dev分支是站在當前的版本去創建的,所以dev分支初始情況下也指向了最新的提交:

一張圖總結:

3.切換分支

我們要想在dev上進行操作,就必須把dev分支當作工作分支。那如何切換到dev分支下進行開發呢?使用

git checkout <分支名>

命令即可完成切換。示例如下:

執行 git checkout dev切換分支后,HEAD就指向了dev,表示我們已經成功地切換到了dev上。隨后,我們在dev分支下修改ReadMe文件,在末尾新增了一行內容 aaa on dev branch,并進行了一次提交操作。

現在,dev分支的工作完成,我們切換回master分支:

hyb@139-159-150-152:~/gitcode$ git checkout master 
Switched to branch 'master'

切換回master分支后再查看ReadMe文件內容,此時發現ReadMe文件中剛才新增的內容不見了:

而再切回dev查看,剛才新增的內容又有了:

為什么會出現這個現象呢?

我們來看看dev分支和master分支的指向,發現dev和master兩者此時指向的提交已經不一樣了:

hyb@139-159-150-152:~/gitcode$cat.git/refs/heads/dev
bdaf528ffbb8e05aee34d37685408f0e315e31a4    # dev和剛創建時相比已經發生了改變
hyb@139-159-150-152:~/gitcode$cat.git/refs/heads/master
5476bdeb12510f7cd72ac4766db7988925ebd302

進一步的,可以通過命令

git cat-file -p bdaf528ffbb8e05aee34d37685408f0e315e31a4

來查看此時dev所指向的提交的詳情。查詢到的詳情中,parent關鍵字標識了當前commit的上一個commit是哪一個。可以看到,dev當前指向的上一個指向,正是剛創建dev時dev的指向。因為我們是在dev分支上提交的,所以dev會指向最新的提交;而master分支此刻的指向并沒有改變(正如兩個平行宇宙之間彼此獨立的)。

master的視角下,當然就看不到在dev下的提交了,因此在master和dev兩個分支下的ReadMe文件內容會有差別。

4.合并分支

為了在master主分支上能看到新的提交,就需要將dev分支合并到master分支。

使用

git merge dev

命令,示例如下:

git merge命令用于合并指定分支到當前分支。合并后,master分支上就能看到dev分支提交的內容了。此時的狀態如圖如下所示:?

仍然可以用 cat .git/refs/heads/master命令和 cat .git/refs/heads/dev命令分別查看master和dev的指向,此時發現二者指向再次相同,dev中存儲的commitID也被同步給了master。

By the way,細心的朋友可能注意到,剛才merge操作后,結果其實有些特殊:

這里的 Fast-forward?代表“快進模式”,它是Git分支合并的一種方式。快進模式意味著合并的方式是直接把master指向dev的當前提交,所以合并速度非常快。當然,也不是每次合并都是Fast-forward,我們后面會講其他方式的合并。

5.創建、切換、合并分支流程圖

1、創建新的dev分支。

2、git checkout dev:切換至dev分支。

3、在dev分支上commit。

4、切換回master分支,git merge dev

6.刪除分支?

合并完成后,dev分支對于我們來說就沒用了,那么dev分支就可以被刪除掉。刪除分支的命令為:

git branch -d <分支名>

注意,如果當前正處于dev分支下,是不能刪除dev分支本身的:

hyb@139-159-150-152:~/gitcode$ git branch
*devmaster
hyb@139-159-150-152:~/gitcode$ git branch -d dev
error:Cannot delete branch 'dev' checked out at'/home/hyb/gitcode'

要刪除當前分支,只能先切換到其他分支下,再執行刪除操作,如:

hyb@139-159-150-152:~/gitcode$ git checkout master
Switched to branch 'master'
hyb@139-159-150-152:~/gitcode$ git branch -d dev
Deleted branch dev(was bdaf528).
hyb@139-159-150-152:~/gitcode$ git branch
* master

此時的狀態如圖如下所示:

因為創建、合并和刪除分支非常快,所以Git鼓勵你使用分支完成某個任務,合并后再刪掉分支,這和直接在master分支上工作效果是一樣的,但過程更安全(“安全”正是使用分支的一個原因)。

7.合并沖突

在實際中,分支并不是想合并就一定能合并成功的,有時可能會遇到代碼沖突的問題。

為了演示這問題,我們創建一個新的分支 dev1 ,并切換至目標分支。

注意,可以使用

git checkout -b dev1

一步完成創建并切換的動作,示例如下:

git checkout -b dev1

git branch dev1 + git checkout dev1

效果是相等的。

我們在dev1分支下修改ReadMe文件,將 aaa on dev branch 改為 bbb on dev branch,然后提交:

此時在dev1分支中,ReadMe文件最終修改并提交的結果為 bbb on dev branch。

切回master分支,然后在master分支下將ReadMe文件最終修改并提交為 ccc on dev branch:

現在master分支和dev1分支中都各自有了新的提交:

Git只能試圖把各自的修改合并起來,但這種合并可能會有沖突。

在master分支中執行 git merge dev1 ,將dev1分支與master分支上提交的修改合并,結果如下:

發現ReadMe文件有沖突后,可以直接查看文件內容來查看沖突詳情。Git會用<<<<<<<,=======,>>>>>>>來標記出不同分支沖突的具體內容,如下所示:

此時我們要做的是手動調整發生沖突的代碼(將不要的內容手動刪除,把要的內容保留下來),并需要再次提交修正后的結果!!

(再次提交很重要,切勿忘記)

到這里沖突就解決完成,此時的狀態變成了:

補充:查看分支合并的情況

用帶參數的 git log?命令可以看到分支的合并情況:

命令:git log --graph --abbrev-commit

上圖中,星號? *? 代表的就是之前的“提交(commit)”。

最后,不要忘記dev1分支使用完畢后就可以刪除了:git branch -d dev

8.分支管理策略

Fast Forward 模式(ff模式)

通常合并分支時,如果可以,Git 會采用?Fast forward 模式。

Fast forward 模式形成的合并結果:

在Fast forward模式下,當我們合并分支后查看分支歷史時,分支歷史的展示中會丟失部分分支信息,即看不出來最新的提交到底是merge進來的還是正常提交的

非Fast Forward模式(no-ff模式)

我們知道,當發生合并沖突時,在解決沖突問題后還需要再進行一次新的commit,然后才能得到最終狀態:

這里就不是 Fast forward 模式了。

在非 Fast forward 模式中,從分支歷史上是可以看出分支信息的。例如我們現在已經刪除了在合并沖突部分創建的 dev1 分支,但依舊能看到 master 其實是由其他分支合并得到的:

如何在正常提交的時也選擇no-ff模式呢?

Git支持我們強制禁用fast forward,那么就會在 merge 時生成?個新的 commit 。這樣,從分?歷史中就可以看出分支信息。

在執行 git merge 時添加 --no-ff 選項,就表示不使用ff模式。--no-ff選項表示的就是禁用 Fast forward 模式。禁用 Fast forward 模式后,在合并分支后會創建一個新的 commit ,所以要加上-m參數,把描述(message)也寫進去:

由下面的圖可知,在no-ff模式下生成一個新的commit,最終master也會指向一個新的提交:

ff模式和no-ff模式最大的區別是,用 git log --graph --abbrev-commit命令查看提交日志時,能否區別出git的master中的每個commit是merge進來的還是正常提交的。

(在企業實操中一般更建議使用no-ff模式。)

9.分支策略

在實際開發中,我們應該按照幾個基本原則進行分支管理:

  1. 首先,master分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面干活。

  2. 干活都在dev分支上。(dev分支是不穩定的,到某個時候,比如1.0版本發布時,再把dev分支合并到master上,在master分支發布1.0版本)。

你和你的小伙伴們每個人都在dev分支上干活,每個人都有自己的分支,時不時地往dev分支上合并就可以了。

所以,團隊合作的分支看起來就像這樣:

10.bug分支

假設我們現在正在 dev2 分支上進行開發,開發到一半還沒提交,突然發現 master 分支(即線上環境的代碼)上有嚴重的 bug(如閃退之類的),需要馬上解決。

直接在master主分支上編輯代碼進行bug修復,這肯定是不可以的。

安全起見,必須遵守分支的策略,即在本地創建一個新的臨時分支來修復,修復后,經過測試團隊的測試后將穩定的代碼合并到master分支,然后將臨時分支刪除。

可現在dev2的代碼在工作區中開發了一半,還無法提交,而要修復master中的bug怎么辦?

dev2中的修改都在工作區中,dev2在工作區中的做的修改會影響在其余分支的工作區進行工作。此時就需要先對dev2工作區中的內容進行保存。Git 提供了

git stash

命令,可以將當前的工作區信息進行儲藏,被儲藏的內容可以在將來某個時間恢復出來:

執行完git stash命令后,tree ./git,可以查看到當前git目錄下多了一個stash目錄,dev2的修改就被存儲在這個stash目錄中:?

git stash后用git status查看工作區,工作區是干凈的(除非有沒有被 Git 管理的文件),因此可以放心地創建分支來修復bug:

注意,如果工作區還有沒被 git 管理起來的文件,則該文件不能被暫存起來:

儲藏dev2工作區之后,由于我們要基于master分支修復bug,所以需要切回分支,再新建臨時分支來修復bug,示例如下:

修復完成后,切換回master主分支,并將bug分支合并到master分支,最后刪除bug分支即可:

至此,針對master主分支上的bug修復工作(即:切回主分支,拉一個bug_fix新分支,在bug_fix上修復完bug后再合并到master這樣的一系列操作)已經做完了,我們還要繼續回到dev2分支進行一開始未完成的內容的開發。

切換回dev2分支:

在dev2分支下檢查 git status會發現,工作區是干凈的:

hyb@bite:~/gitcode$ git status
On branch dev2
nothing to commit, working tree clean

可以用git stash list查看stash存放哪些內容,使用

git stash pop

命令來恢復現場,恢復的同時會把stash中的內容刪了,示例如下:?

補充: 恢復現場除了 git stash pop, 也可以采? git stash apply 。但是,用git stash apply恢復后,stash內容并不刪除,需要我們自己調? git stash drop 來刪除。可以多次進行git stash,恢復的時候,先? git stash list 查看,然后恢復指定的stash,?命令git stash apply stash@{0}即可。

再次查看stash中的內容,我們已經發現已經沒有現場可以恢復了:?

hyb@bite:~/gitcode$ git stash list
# 沒有內容顯示

恢復完工作區的代碼之后,我們便可以繼續在dev2完成開發,開發完成后便可以進行提交:

但修復bug的內容并沒有在 dev2 上顯示。

為什么dev2下的ReadMe文件中,內容還是abcde而不是abcdef呢?這是因為創建dev2的時候,是基于還未修復的master的,也就是還有bug的master的。

此時的狀態圖為:

最終目的是要讓 master 分支和 dev2 分支合并。正常情況下我們切回 master 分支,直接將dev2分支的內容合并到master中即可,但這樣其實是有一定風險的。

因為在master分支與dev2分支合并時可能會發生沖突,而代碼沖突需要我們手動解決(在 master 上解決)。我們無法保證對于沖突問題可以正確地一次性解決掉,因為在實際的項目中,代碼沖突不只一兩行那么簡單,有可能幾十上百行,甚至更多,解決的過程中難免手誤出錯,導致錯誤的代碼被合并到 master 上。此時的狀態為:

解決這個問題的一個好的建議是:先在自己的dev2分支上合并 master主分支,再讓 master 去合并dev2分支。這樣做的目的是,一旦有沖突可以在本地分支dev2上解決并進行測試,而不影響 master 。

此時的狀態為:

實操演示如下:

最后執行 git branch -d ,將已經完成使命的dev2分支和bug_fix分支合并即可。

疑問解決

對于上述分支策略下的一系列操作,有的朋友可能會有疑問:dev2從master中拉出來的時候,ReadMe文件內容是abcde;但是master后來又拉了bug_fix分支,并把內容改成了 abcdef。如果工作區是共享的話,在bug_fix分支更改為abcdef的時候為什么沒有影響到dev2分支呢?

原因:

abcdef已經提交了,屬于版本庫的內容,對于master來說,此時工作區是干凈(clean)的,無變動。工作區是干凈的,那么dev2分支的工作區也是干凈的。git是基于提交來管理文件的,提交之前工作區共享。提交之后,提交的內容就已經被隔離了。

也就是說,如果bug_fix分支改成abcdef之后,沒有進行add操作,那么bug_fix、master和dev2三個分支工作區的內容都會是abcdef;而如果bug_fix提交修改之后,工作區變成干凈的,其他的分支的工作區也會變回原本的樣子。

11.刪除臨時分支

軟件開發中,總有無窮無盡的新的功能要不斷添加進來。

添加一個新功能時,我們肯定不希望一些實驗性質的代碼把主分支搞亂了。所以,每添加一個新功能,最好新建一個分支,我們可以將其稱之為 feature 分支。在feature 分支上進行開發,開發完成后再合并,最后刪除該 feature 分支。

可是,如果我們今天正在某個 feature 分支上開發了一半,被產品經理突然叫停,說是要停止新功能的開發。雖然白干了,但是這個 feature 分支還是必須就地銷毀,留著無用了。

這時使用原來的 git branch -d 命令刪除分支的方法是不行的。

之前之所以有可以用git branch -d刪除分支的情況,是因為當時已經把分支和master主分支merge過了。而如果當前分支沒有和master主分支merge過、且已在當前分支進行過一些提交的時,git是會在刪除時保護當前分支的(git認為只要分支被創建出來了且在上面有過提交,那么這個分支就是有用的,不能隨便刪除)。

使用

git branch -D

命令則可以強制刪除:

12.分支小結

分支在實際中有什么用呢?

假設你準備開發一個新功能,但是需要兩周才能完成,第一周你寫了50%的代碼,如果立刻提交,由于代碼還沒寫完,不完整的代碼庫會導致別人不能干活了。如果等代碼全部寫完再一次提交,又存在丟失每天進度的巨大風險。現在有了分支,就不用怕了。你創建了一個屬于你自己的分支,別人看不到,還繼續在原來的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到開發完畢后,再一次性合并到原來的分支上,這樣既安全,又不影響別人工作。

并且 Git 無論創建、切換和刪除分支,Git在1秒鐘之內就能完成!無論你的版本庫是1個文件還是1萬個文件。


六、遠程操作

1.理解分布式版本控制系統

我們目前所說的所有內容(工作區,暫存區,版本庫等等),都是在本地,也就是在你的筆記本或者計算機上。而我們的Git其實是分布式版本控制系統。什么意思呢?

可以簡單理解為,我們每個人的電腦上都是一個完整的版本庫,這樣你工作的時候,就不需要聯網了,因為版本庫就在你自己的電腦上。既然每個人電腦上都有一個完整的版本庫,那多個人如何協作呢?比方說你在自己電腦上改了文件A,你的同事也在他的電腦上改了文件A,這時,你們倆之間只需把各自的修改推送給對方,就可以互相看到對方的修改了。

分布式版本控制系統的安全性要高很多,因為每個人電腦里都有完整的版本庫,某一個人的電腦壞掉了不要緊,隨便從其他人那里復制一個就可以了。

在實際使用分布式版本控制系統的時候,其實很少在兩人之間的電腦上推送版本庫的修改,因為可能你們倆不在一個局域網內,兩臺電腦互相訪問不了。也可能今天你的同事病了,他的電腦壓根沒有開機。因此,分布式版本控制系統通常也有一臺充當“中央服務器”的電腦,但這個服務器的作用僅僅是用來方便“交換”大家的修改,沒有它大家也一樣干活,只是交換修改不方便而已。有了這個“中央服務器”的電腦,這樣就不怕本地出現什么故障了(比如運氣差,硬盤壞了,上面的所有東西全部丟失,包括git的所有內容)。

2.遠程倉庫

Git是分布式版本控制系統,同一個Git倉庫,可以分布到不同的機器上。怎么分布呢?最早,肯定只有一臺機器有一個原始版本庫,此后,別的機器可以“克隆”這個原始版本庫,而且每臺機器的版本庫其實都是一樣的,并沒有主次之分。

你肯定會想,至少需要兩臺機器才能玩遠程庫不是?但是我只有一臺電腦,怎么玩?

其實一臺電腦上也是可以克隆多個版本庫的,只要不在同一個目錄下。不過,現實生活中是不會有人這么傻的在一臺電腦上搞幾個遠程庫玩,因為一臺電腦上搞幾個遠程庫完全沒有意義,而且硬盤掛了會導致所有庫都掛掉,所以我也不告訴你在一臺電腦上怎么克隆多個倉庫。

實際情況往往是這樣,找一臺電腦充當服務器的角色,每天24小時開機,其他每個人都從這個“服務器”倉庫克隆一份到自己的電腦上,并且各自把各自的提交推送到服務器倉庫里,也從服務器倉庫中拉取別人的提交。

完全可以自己搭建一臺運行Git的服務器,不過現階段,為了學Git先搭個服務器絕對是小題大作。好在這個世界上有個叫GitHub的神奇的網站,從名字就可以看出,這個網站就是提供Git倉庫托管服務的,所以,只要注冊一個GitHub賬號,就可以免費獲得Git遠程倉庫。

這里貼一個博主本人的Github主頁:GitHub,里面分享了一些開源項目,歡迎來訪交流。

不過,Github是國外的網站,速度比較慢。而國內也有好用的開源平臺,即Gitee(碼云)。

這里采用碼云來托管代碼,我們從零開始來使用一下碼云遠程倉庫。

新建遠程倉庫

1、新建遠程項目倉庫:

2、填寫基本信息:

3、創建成功:

4、創建成功后,我們可以對遠程倉庫進行一個基本的設置:開源or私有

5、也可以在設置-倉庫成員管理中管理協作者:

6、從創建好的遠程倉庫中我們便能看到,之前在本地學習過的分支,也存在于遠程倉庫中并被管理起來了。剛創建的倉庫有且只有一個默認的master分支:

Issues

當把倉庫設置為開源后,所有的用戶都可以瀏覽這個倉庫的內容。如果瀏覽者發現了你倉庫中代碼的bug,該怎么和你聯系呢?

gitee和github都提供了Issues功能,這個功能是讓倉庫的瀏覽者和倉庫的成員進行交流的地方。

點擊「新建Issue」,就進入編輯Issue的頁面:

選擇完畢之后,點擊「創建」,在Issues版塊中就會顯示剛才提交的問題:

如果已經處理完這個bug,那么可以繼續進入問題詳情更改問題的狀態:

Pull Request

實際開發中,直接允許dev分支的內容合并到master分支上是非常不安全的,很容易影響master分支上代碼的穩定性。

因此,在有dev分支與master分支合并的需要時,應當由開發者提出一個dev分支的PR(即Pull Request,合并申請單)給倉庫的管理員,PR中需要包含dev分支的一些信息,如做了什么改動、為什么要合并等。只有倉庫管理員同意了,才能將dev中的代碼merge到master中去。

倉庫的PR信息在Pull Request版塊可以看:

在創建項目時,也可以選擇Pull Request的模板。

克隆遠程倉庫

克隆/下載遠端倉庫到本地,需要使用 git clone 命令,后面跟上我們的遠端倉庫的鏈接。

遠端倉庫的鏈接可以從倉庫中找到:選擇“克隆/下載”獲取遠程倉庫鏈接:

SSH協議和HTTPS協議是Git最常使用的兩種數據傳輸協議。

SSH協議使用了公鑰加密和公鑰登錄機制,體現了其實用性和安全性,使用此協議需要將我們的公鑰放上服務器,由Git服務器進行管理(Git服務器就由gitee平臺代替了,gitee平臺上有地方可以配置本地服務器的公鑰,等到使用ssh協議的時候再來配置)。

使用HTTPS方式時,沒有任何要求,可以直接克隆下來。

HTTPS協議克隆

在執行克隆 git clone 操作時,不能在本地倉庫(.git)所在的目錄下執行,其他地方都可以執行:

origin是遠程倉庫默認的倉庫名,可以用 git remote 命令來查詢遠程倉庫信息:

上面顯示了可以抓取和推送的origin的地址。如果沒有push / fetch權限,就看不到相應的push / fetch的地址。fetch和push表示當前本地倉庫擁有對遠程倉庫的抓取權限和推送權限:

  1. 克隆遠程倉庫后,所有的操作是在本地來完成的,本地提交的修改如何推送到遠端呢?就要使用到push權限去push遠端倉庫的地址

  2. fetch表示抓取,如果遠程倉庫中存在一些本地沒有的內容時,就需要去遠程倉庫獲取新的內容,這就要使用到fech權限。

有了這兩個權限,才能讓本地倉庫和遠程倉庫之間有一些交互的操作。

SSH協議克隆

SSH協議使用的是公鑰加密和公鑰登錄的機制。

如果要使用SSH協議來進行git倉庫克隆,必須要把自己本地服務器上的公鑰放到git服務器上來進行管理,才可以克隆成功。

可以在設置頁中查看公鑰的使用情況:

在沒有配置任何公鑰的情況下進行SSH克隆:

使用SSH方式克隆倉庫,由于我們沒有添加公鑰到遠端庫中,服務器拒絕了我們的clone鏈接。需要我們設置一下。

如何在本地服務器上查看公鑰的內容?

首先在用戶主目錄(即家目錄,cd ~)下,看看有沒有.ssh目錄,如果有,再看看這個目錄下有沒有id_rsa(私鑰,保存在自己的服務器上,不對外展示)和id_rsa.pub(公鑰)這兩個文件。如果有公鑰,那直接把公鑰的內容復制到上面的頁面中即可。

如果已經有了,可直接跳到下一步。如果沒有,需要創建SSHKey。

~目錄下使用命令:

ssh-keygen -t rsa -C "<你在gitee上綁定的郵箱地址>"

gitee上綁定的個人郵箱地址在設置頁中查看:

此時命令就是:

ssh-keygen -t rsa -C "xxxxxxxxxx@qq.com"

注意輸入自己的郵箱,然后一路回車,都使用默認值即可:

此時就把我們的公鑰和私鑰都創建好了。可以在用戶主目錄里找到 .ssh 目錄,里面有 id_rsaid_rsa.pub 兩個文件,這兩個就是SSH Key的秘鑰對, id_rsa 是私鑰,不能泄露出去;id_rsa.pub 是公鑰,可以放心地告訴任何人。

cat一下公鑰,將其中的內容一字不差地復制粘貼到gitee的公鑰配置頁面即可。

然后添加自己的公鑰到遠端倉庫:

配置好后可見:

點擊確認后,需要對你進行認證,輸入你的賬號密碼即可。至此,我們的準備工作全部做完,可以開始歡快地clone了~

done,成功!

如果有多個人協作開發,GitHub/Gitee允許添加多個公鑰,只要把每個人的電腦上的公鑰都添加到GitHub/Gitee,就可以在每臺電腦上往GitHub/Gitee上提交推送了。

向遠程倉庫推送 push

當本地倉庫的內容領先于遠程倉庫時,就可以通過本地向遠程倉庫推送的方式把本地最新的修改推送上去。

將遠程倉庫克隆下來后,依然要先配置本地git倉庫的配置項,使用 git config -l 命令:

本地倉庫的郵箱和用戶名必須與遠程倉庫的郵箱用戶名一致。如果之前配置過 --global 的config,那么遠程倉庫拉到本地時,user和email也會自動使用之前配置的global配置項。若本地的配置和遠程倉庫的配置不一樣,則會出錯;若從來沒有配置過global配置項,那么克隆到本地的本地倉庫是沒有用戶名和郵箱配置項的,第一次提交時也會報錯,需要重新配置。

可直接更改:

git config --global user.email "<郵箱地址>"git config --global user.name "<用戶名>"

當我們從遠程倉庫克隆后,Git會自動把本地的master分支和遠程的master分支對應起來,并且,遠程倉庫的默認名稱是origin。

在本地我們仍然可以使用git remote命令來查看遠程庫的信息,或者用git remote -v顯示更詳細的信息。

如何把本地倉庫中的修改推送到遠程倉庫中?

將本地倉庫的內容推送至遠程倉庫,需要使用push命令,該命令用于將本地的分支版本上傳到遠程并合并,如果遠程倉庫下當前并沒有push命令中指定的遠程分支名,則會自動在遠程創建。

命令格式如下:

git push <遠程主機名> <本地分支名>:<遠程分支名># 如果本地分支名與遠程分支名相同,則可以省略冒號
git push <遠程主機名> <本地分支名>

此時我們要將本地的master分支推送到origin主機的master分支:

推送成功!這里由于我們使用的是SSH協議,是不用每一次推送都輸入密碼的,方便了我們的推送操作。如果你使用的是HTTPS協議,有個麻煩地方就是每次推送都必須輸入口令。

接下來看碼云遠端,就能看到本地的代碼已經被推送上來了。

拉取遠程倉庫

當遠程倉庫的內容領先于本地倉庫時,可以通過拉取遠程倉庫來把遠程倉庫的修改拉取到本地。

使用 pull 命令。

注意:不要直接在遠程倉庫更改任何的代碼,如果要改,也要在本地改完再推送上去。

這里用于模擬遠程倉庫內容領先于本地倉庫的情況:

1、在gitee上點擊README.md文件并在線修改它。

2、修改內容。

此時,遠程倉庫是要領先于本地倉庫一個版本,為了使本地倉庫保持最新的版本,我們需要拉取下遠端代碼,并合并到本地。

git pull

命令會從遠程倉庫獲取更新,并自動將這些更新合并到當前所在的本地分支。【pull等于拉取+合并】

當運行 git pull 時,它其實執行了兩個操作:git fetchgit merge

首先,它使用 git fetch 從遠程倉庫獲取最新的提交和文件,并將這些更新存儲在本地的遠程跟蹤分支中(例如origin/main(遠程跟蹤分支的名稱由遠程倉庫名和分支名組成,它們用斜杠 / 分隔))。

接著,它自動使用 git merge 將遠程跟蹤分支的內容合并到當前所在的本地分支

Git提供了命令,該命令用于從遠程獲取代碼并合并本地的版本。格式如下:

git pull <遠程主機名> <遠程分支名>:<本地分支名># 如果遠程分支與當前分支名稱相同,則冒號后面的部分可以省略。
git pull <遠程主機名> <遠程分支名>

同名分支對應關系時冒號可以省略:如果你當前的本地分支與遠程分支存在同名且已經建立了追蹤關系,那么可以直接執行 git pull,Git 會自動識別并拉取對應的遠程分支。例如:

如果你當前在本地的 master 分支上,并且要拉取遠程倉庫的 origin/master 分支,那么可以省略冒號的使用。

通常情況下,如果沒有指定遠程倉庫和分支,則會將與當前本地分支相關聯的遠程分支合并到本地分支。

如果你不在 dev 分支上,也可以使用以下方式在不用切換到dev分支的前提下就能將遠程 origindev 分支到本地的 dev 分支上。

git pull origin dev:dev

3.配置Git

忽略特殊文件

在日常開發中,我們有些文件不想或者不應該提交到遠端,比如保存了數據庫密碼的配置文件。

那怎么讓Git知道呢?在Git工作區的根目錄下創建一個特殊的.gitignore文件,然后把要忽略的文件名填進去,Git就不會追蹤管理這些文件了。

不需要我們自己從頭寫.gitignore文件,gitee在創建倉庫時就可以為我們生成。在創建git倉庫時,有一個初始化倉庫的選項,里面有一個“添加 .gitignore模板”:

當然,如果我們要寫的是Java程序,那么就可以選擇Java的.gitignore文件模板。

選擇完畢后點擊創建,就會在倉庫中自動生成一個.gitignore文件,并且文件中的內容會根據我們所選的模板來進行初始化。

如果當時創建倉庫的時候沒有選擇.gitignore文件模板,那么自己在工作區創建一個也是可以的。

例如我們想忽略以 .so.ini 結尾所有文件,.gitignore 的內容如下:

#省略選擇模本的內容
...# Myconfigurations:
# 可以直接寫文件名(指定某個確定的文件),也可以用通配符
*.ini
*.so

檢驗 .gitignore 的標準是 git status 命令是不是說 working tree clean 。我們發現Git 并沒有提示在工作區中有文件新增,說明 .gitignore 生效了:

以下的演示中,.gitignore文件是本地新創建的,還沒有commit或推送給遠端,因此它本身的修改也會被記錄,就沒有顯示working tree clean了。

但有些時候,你就是想添加一個文件到 Git,但由于這個文件被 .gitignore 忽略了,根本添加不了怎么辦呢?

1、方法一

可以在add時加上 -f 選項進行強制add:

git add -f b.so

但不建議使用這種方式,因為最好不要違背.gitignore文件中的配置。

2、方法二

有些時候,當我們編寫了規則排除了部分文件時,比如.*,但是我們發現 .* 這個規則把 .gitignore 也排除了。此時不想更改.gitignore規則又要做到不把.gitignore排除,可以在.gitignore文件中編輯規則:

把指定文件排除在 .gitignore 規則外的寫法就是 ! +文件名,所以,只需把例外文件添加進去即可。

  • Changes to be commited:已經add了,提示需要commit

  • Changes not staged for commit:曾經已經提交過的文件,已經被git管理了,然后再去修改就會有這個提示。

  • Untracked files:新建的文件,git還未追蹤管理它

如果一個文件沒有被git管理,但又忘記是否存入.gitignore中,可以使用命令進行ignore規則檢查:

git check-ignore -v <文件名>

來查看原因。

給命令配置別名

我們可以通過

git config [--global] alias.別名 原命令名

的方式來給git命令配置別名。

如將 git status 簡化為 git st ,對應的命令為:

git config --global alias.st status

--global參數是全局參數,也就是這些命令在這臺電腦的所有Git倉庫下都有用。如果不加,那只針對當前的倉庫起作用。

再來將git log -l配置為 git last ,讓其顯示最后一次提交信息:

git config --global alias.last 'log -1'

再將查看提交日志(--pretty=oneline意思是以一行的格式打印, --abbrev-commit意思是只打印commit id的前幾位數)

git log --pretty=oneline --abbrev-commit這一命令配置為更為簡短的git lpa

不過還是不推薦大家太早去使用它,還是應當所有的Git命令都手動輸入,以盡快熟悉Git。

**小結

本篇涉及的部分git命令:

git cat-file -p <commit ID>:查看提交信息

git branch:顯示當前所有分支

git branch <分支名>:創建分支

git checkout <分支名>:切換分支

git merge <分支名>:合并分支

git checkout <分支名>:切換分支

git branch -d <分支名>:刪除分支(非強制)

git branch -D?<分支名>:刪除分支(強制)

git checkout -b <分支名>:創建并切換分支

git log --graph --abbrev-commit:查看分支合并情況

git stash:儲藏工作區內容

git stash list:查看stash存放哪些內容

git stash pop:恢復工作區內容

git clone:克隆遠程倉庫

git push:將本地的分支版本上傳到遠程并合并

git fetch:從遠程倉庫獲取最新的提交和文件

**下篇內容

七、標簽管理

八、多人協作

九、企業級開發模型

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/12359.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/12359.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/12359.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java約拍攝影小程序

獲取源碼配套資料論文等、問題解答&#xff0c;可以加華神扣扣&#xff1a;3753599439 扣扣&#xff1a;1590404240 叩叩&#xff1a;1306749621

Java窗口函數框架JDFrame

1、簡介 在上一節中已經介紹過 JDFrame&#xff0c;文章鏈接stream流太難用了看看JDFrame 沒看過的朋友可以先看看&#xff0c; 這次主要講講窗口函數相關API的使用 在各種數據庫mysql&#xff0c; hive、spark中都有非常好用的開窗函數使用&#xff0c; 但是java卻沒好用的J…

數據結構與算法學習筆記十---鏈隊列的表示和實現(C語言)

目錄 前言 1.什么是鏈隊 2.鏈隊的表示和實現 1.定義 2.初始化 3.銷毀 4.清空 5.空隊列 6.隊列長度 7.獲取隊頭 8.入隊 9.出隊 10.遍歷隊列 11.完整代碼 前言 本篇博客介紹鏈棧隊列的表示和實現。 1.什么是鏈隊 鏈隊是采用鏈式存儲結構實現的隊列。通常鏈隊使用單…

【知識拓展】大白話說清楚:IP地址、子網掩碼、網關、DNS等

前言 工作中常聽別人說的本地網絡是什么意思&#xff1f;同一網段又是什么意思&#xff1f;它倆有關系嗎&#xff1f; 在工作中內經常會遇到相關的網絡問題&#xff0c;涉及網絡通信中一些常見的詞匯&#xff0c;如IP地址、子網掩碼、網關和DNS等。具體一點&#xff1a;經常會…

申請免費的必應搜索API

申請免費的必應搜索API 文章目錄 申請免費的必應搜索API前言一、原理1.1 登錄1.2 進入1.3 獲取密鑰1.4 申請VISA信用卡1.5 創建必應自定義搜索資源 二、創建成功 前言 準備條件&#xff1a; 1、outlook郵箱 2、招商銀行全幣種VISA信用卡【建議之前就有一張招商銀行信用卡&…

【opencv】圖像拼接實驗

實驗環境&#xff1a;anaconda、jupyter notebook 實驗用到的包&#xff1a;opencv、matplotlib、numpy 注&#xff1a;opencv在3.4.2之后sift就不是免費的了 我用的是3.4.1.15版本 實驗使用到的圖片 一、sift函數獲取特征值 讀入圖片 book cv2.imread(book.png, cv2.IMRE…

【極簡】如何估算大模型inference所需的內存量

1字節8bit 16float2字節 模型后面的xxb的單位是字節。 1b 字節≈ 0.93G&#xff0c;這個是以8bit運行&#xff0c;4bit減半&#xff0c;16bit&#xff08;float&#xff09;加倍&#xff0c;32bit&#xff08;double&#xff09;炒雞加倍。 剩下的是小頭&#xff0c;需要參數計…

蘋果macOS無法給App麥克風授權解決辦法

好久沒有在電腦上錄制課程了&#xff0c;有些東西還是錄下來記憶深刻&#xff0c;卻意外發現MAC系統升級后無法授權給第三方的App使用攝像頭和麥克風&#xff0c;而錄屏軟件是需要開啟麥克風和攝像頭才能錄制屏幕上的操作和聲音&#xff0c;官方提示在第三方APP若有使用攝像頭和…

css的4種導入方式

熟悉CSS樣式4種的引用方式&#xff0c;分別為行內式、內嵌式、鏈入式和導入式。 行內式 <標簽名 style"屬性1:屬性值1;屬性2:屬性值2;屬性3:屬性值3;">內容</ 標簽名>style是標簽的屬性&#xff0c;實際上任何HTML標簽都擁有style屬性&#xff0c;用來…

pyqt QComboBox下拉列表框控件

pyqt QComboBox下拉列表框控件 QComboBox效果代碼 QComboBox QComboBox 是 PyQt&#xff08;中的一個控件&#xff0c;它允許用戶從下拉列表中選擇一個選項。這個控件在需要用戶從預定義選項中進行選擇時非常有用。 效果 代碼 import sys from PyQt5.QtWidgets import QAppl…

vite創建的項目使用rem適配

下面以創建vue3.0 項目為例&#xff1a; npm init vitelatest “名稱” 選擇vue &#xff08;選擇你所對應的語言&#xff09; 更具提示步驟執行 cd xxx npm i npm run dev 然后再項目中使用 rem 需要安裝插件 第一步安裝插件 npm i amfe-flexible npm i postcss-pxtorem 第二…

CS144 Checkpoint 4: interoperating in the world(2024)

分析網絡路徑和性能&#xff1a; mtr命令 mtr 輸出的詳細分析&#xff1a; mtr 162.105.253.58 命令用于結合 traceroute 和 ping 的功能&#xff0c;實時監測并分析從你的計算機到目標主機&#xff08;IP 地址 162.105.253.58&#xff0c;北京大學計算中心&#xff09;之間…

Nginx配置Referer防盜鏈

系列文章目錄 文章目錄 系列文章目錄前言 前言 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到網站&#xff0c;這篇文章男女通用&#xff0c;看懂了就去分享給你的碼吧。 HTTP Referer是Hea…

PBOOTCMS|URL靜態制作教程(已解答)

0、先解壓源碼文件&#xff0c;在覆蓋靜態文件&#xff0c;全部點是。 打開程序后臺登錄地址www.xxx.com(你的域名)/admin.php/Menu/index 打開程序后臺--系統菜單--菜單新增&#xff08;清理緩存后重新登錄賬號&#xff09; &#xff08;選擇父菜單&#xff0c;菜單名稱&#…

ROS2+TurtleBot3+Cartographer+Nav2實現slam建圖和導航

0 引言 入門機器人最常見的應用就是slam建圖和導航&#xff0c;本文將詳細介紹這一流程&#xff0c; 便于初學這快速上手。 首先對需要用到的軟件包就行簡單介紹。 turtlebot3: 是一個小型的&#xff0c;基于ros的移動機器人。 學習機器人的很多示例程序都是基于turtlebot3。 …

【Java基礎】枚舉類的方法及應用

如何實現讓一個類有固定個數的對象 手動封裝構造方法&#xff08;private&#xff09; → 創建靜態對象 → final修飾靜態對象&#xff0c;使其成為常量 class Season { //枚舉類public final static Season SPRING new Season();public final static Season SUMMER new Se…

MySQL數據庫備份全攻略:從基礎到高級,一文掌握所有備份技巧

在數據為王的時代&#xff0c;數據庫的備份無疑是每一位數據庫管理員&#xff08;DBA&#xff09;和開發者必須掌握的核心技能。MySQL作為世界上最流行的開源關系型數據庫管理系統&#xff0c;其備份策略的多樣性和靈活性更是值得我們深入探討。今天&#xff0c;我們將從基礎的…

廢品回收微信小程序基于FastAdmin+ThinkPHP+UniApp(源碼搭建/上線/運營/售后/更新)

一款基于FastAdminThinkPHPUniApp開發的廢品回收系統&#xff0c;適用廢品回收站、再生資源回收公司上門回收使用的小程序。 一、FastAdmin框架特色功能及優勢 模塊化開發&#xff1a;控制器、模型、視圖、JS一一對應&#xff0c;使用RequireJS進行插件機制&#xff0c;支持插…

Java面試題:線程池的核心參數和工作原理

線程池的核心參數 ThreadPoolExecutor(int corePoolSize,//核心線程數目int MaximumPoolSize,//最大線程數核心線程臨時線程long keepAliveTime,//臨時線程的存活時間,在存活時間內如果沒有新任務,線程資源會被釋放TimeUnit unit,//存活時間的時間單位,一個枚舉類型BlockingQu…

sql操作、發送http請求和郵件發送 全棧開發之路——后端篇(2)

全棧開發一條龍——前端篇 第一篇&#xff1a;框架確定、ide設置與項目創建 第二篇&#xff1a;介紹項目文件意義、組件結構與導入以及setup的引入。 第三篇&#xff1a;setup語法&#xff0c;設置響應式數據。 第四篇&#xff1a;數據綁定、計算屬性和watch監視 第五篇 : 組件…