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 也已經出現: