Git多人項目開發流程演練


1. 前言

本文利用 GitHub 平台進行一個多人項目開發流程的演練,以加深課上所學內容。
參考孟老師的文章:五⼤場景玩轉 Git,只要這一篇就夠了!

2. 初始化項目

2.1 新建遠程項目

一個多人項目通常是從遠程創建新倉庫開始,這里我們在 GitHub 新建一個倉庫 git101

新建倉庫時我添加了 .gitignore 文件來進行一個初始化提交,不然默認一個空項目后面不好畫圖演示。.gitignore 文件顧名思義,在里面指定的文件或文件夾都不會被 Git 跟蹤,通常用於指定一些只有本地會用到的文件或者保密性高的私人文件。

值得一提的是,由於某個國家某些自身原因,10月1日開始,GitHub 新倉庫的默認分支名都由原來的 master 變成了 main ,需要改回來的話要手動設置,這里我懶得設置了,main 就 main 吧。

2.2 clone 項目到本地

通常一個多人項目需要在項目中把所有的成員包含進來,給他們寫權限,這樣才能推送自己的代碼到遠程,這里簡單起見,就以網頁端直接修改文件模擬另一位小伙伴的工作。項目路徑有 http 和 ssh 兩種,它們的區別是: http 不需要額外配置,但推送代碼的時候需要驗證身份;ssh 使用秘鑰通信,推送時不需要驗證,但需要額外配置,因為我配置過 ssh ,就直接用 ssh 路徑了:

現在可以開始工作了,首先將項目克隆到本地然后查看一下倉庫分支和提交狀態:

# 克隆項目
git clone 項目地址
# 查看所有分支
git branch -a
# 查看提交記錄
git log --oneline

可以看到添加 .gitignore 時生成的提交記錄以及分支狀態,注意,有一條 remotes/origin/main 分支,這條分支只用於同步遠程倉庫相應分支的狀態,不可直接在這些分支上進行操作,后面同步遠程代碼時會展示它的用法,所以目前倉庫的分支狀態如圖所示,一個節點代表一個提交記錄,分支和HEAD指針通過虛線指向提交記錄:

3. 在本地創建分支完成工作

通常團隊中的每個人負責一個模塊的開發,不能直接在主分支上做開發,要保持它的整潔,這里我們新建一個 dev 分支,在上面做三次提交:

# 新建並切換到 dev 分支
# 相當於兩條命令:git branch dev && git checkout dev
git checkout -b dev

# 將所做修改存到暫存區
git add .
# 提交到本地倉庫
git commit -m "提交說明,沒有空格可不用雙引號"

此時分支狀態如圖:

4. 整理提交記錄

工作完成后,就需要將所做修改合並到主分支了,但在合並之前,我們往往需要對開發分支的提交記錄進行一些整理以保持提交記錄整潔,比如上面的所做的三次提交,或許我們發現 d2 和 d3 所做工作其實干了同一件事,或者 d2 只是隨手提交了一個沒什么意義的 log,總之由於種種原因,我不想讓 d2 出現在最終提交記錄里面了,這時候就可以用 rebase 整理一下提交記錄:

# 整理 HEAD 向前三個提交
git rebase -i HEAD~3

之后會用 vim 打開一個修改提交記錄的文件,里面有刪除合並等各種修改說明,這里我們想刪除 d2 ,所以將前面的 pick 改成 drop:

保存退出后不出意外是有沖突的,因為 d3 是基於 d2 修改的,現在 d2 沒了,就需要解決 d3 產生的沖突,我們可以隨時用 git status 查看工作區狀態:

這里提示 dev.txt 文件存在沖突,那我們就打開 dev.txt ,修改沖突到 d3 的狀態后加入暫存區然后繼續剩下的 rebase 工作:

# 繼續未完成的 rebase 工作
# 如果想撤銷 rebase ,使用 --abort 參數
git rabase --continue

rebase 完成之后還會打開一個 d3 的提交記錄文件,因為修改過這條分支上的提交記錄,理應在最新的提交記錄上做一下說明,這里我就不做修改了:

整理提交記錄后就變成了這個樣子:

5. 合並工作到主分支

合並到主分支非常容易,只需要切換到主分支然后 merge 即可,但在此之前,我們還有些事要辦。

5.1 模擬遠程提交

團隊項目不只有一個人,在我們完成工作時,有可能其他人已經率先提交了工作,這里在網頁端修改 .gitignore 文件來模擬遠程提交:


這里我清空了 .gitignore 文件的內容並添加了一行 *.log ,這表示忽略所有以 .log 結尾的文件,最后將這次提交命名為 r1 ,這時候遠程倉庫的分支狀態發生了改變:

5.2 拉取遠程分支的更新

當遠程存在更新的提交記錄時我們一定不能做合並工作,要始終保持主分支和遠程倉庫一致。
一般在我們對和遠程倉庫有關聯的本地分支做任何修改時都應該先拉取分支狀態,這通常只需要 git pull 即可搞定,它相當於 git fetch && git merge origin/main 兩條命令,在這里我想演示一下遠程分支 origin/master 的作用,所以將兩條命令分開執行:

# fetch 的作用:
# 1. 從遠程倉庫下載本地缺失的提交記錄
# 2. 更新遠程分支(origin/master)到最新狀態(注意,本地分支沒動)
git fetch

# 合並 origin/master 到 main 分支
git merge origin/master


fetch 后的狀態:

merge 后:

5.3 合並開發分支

至此,本地主分支終於和遠程同步了,可以放心的合並開發分支了:

# 合並 dev 到 main
git merge dev

可以看到合並時默認會多出來一個合並節點,暫且叫它 m1 吧,合並后的狀態:

查看分支狀態也可以使用 gitk 命令,只是不怎么好看:

這里還有個問題,合並分支時,如果在分叉后主分支沒有更新的提交記錄,merge 默認行為是快進式合並,就是直接把 dev 分支上面的提交記錄拿過來而不是新建合並節點,這樣做無法保留分支開發的歷史,通常我們需要加上 --no-ff 參數來取消默認行為,它們的區別見下圖:

6. 推送到遠程倉庫

這下本地功能開發完成,也進行了合並,可以放心的推送到遠程倉庫啦:

git push

完成后遠程倉庫分支也進行了更新:

登錄 GitHub 查看,dev.txt 也已經出現:

7. 補充

7.1 關於master和main

嘴上說着 main 就 main,畫圖時還是一不小心寫了 master 上去,這該死的習慣吶。。

話說這種事情能影響到代碼命名也是離譜,哪個程序員看到 master 沒事會聯想到奴隸主??

幾年后,紅黑樹,黑盒測試可能都得換個名字? ̄▽ ̄

7.2 恢復文件新命令

如果你的 Git 版本 >= 2.23,在使用 git status 時可能會注意到一個新命令:

研究了下,原來是之前的 checkout 命令承載了太多的功能,又是分支切換又是文件恢復,有點復雜導致難以學習,社區引入了兩個更易於理解的命令 switch 和 restore 來拆分 checkout,它們的用法也更加直觀。

首先是 switch,沒啥說的,就像它的名字一樣,切換分支:

# -c,或者 --create,新建並切換
git switch dev

然后是 restore,它可以恢復工作區,暫存區,以及任意提交點的文件(但不會回退分支,這仍然需要reset),常用參數說明如下:

# 不加參數時默認是 -W(--worktree),表示恢復工作區(從暫存區取出文件覆蓋工作區)
# -S(--staged),表示恢復暫存區(從最新提交點取出文件覆蓋暫存區)
# -s(--source) commitID或HEAD相對引用,從任意提交點取出文件覆蓋工作區
git restore 文件名或匹配規則

這樣,當我們想撤銷工作區的修改(未add ):

git restore .

當我們想撤銷已經 add 的內容(未commit):

# 僅僅 -S 或者 --staged 只會恢復暫存區而不會恢復到工作區
git restore -SW .

撤銷 commit 需要 reset,而如果我們只需要某個提交點的文件而無需回退:

# 注意這並不會覆蓋暫存區,如果想覆蓋,手動 add 即可
# 想取消本次restore,用默認restore從暫存區取出文件覆蓋工作區即可
git restore -s commitID或者HEAD引用 .

switch 和 restore 還有許多參數,可用 --help 查看,覆蓋了 checkout 幾乎所有功能,這樣一來,checkout 是要逐漸退出舞台了?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM