Git指令在多人協作的專案開發中,扮演了版本控制的核心角色,其重要性不言而喻。照理說,應該在前面的篇幅中提及,但Git指令在開發各階段,一直都有在使用,好像也不能放在特定章節之後,而且一些基本的指令,估計詢問ChatGPT也都能得到解答,故就決定在最後面,針對一些實務上有遇到的問題,彙整需要執行的Git指令組合,主要供查找之用。
Git指令,其實就是將專案的更新,於本機端及遠端專案間傳遞交流。只要先簡單地思考,本機更新檔案如何傳送到遠端(push
),以及遠端的檔案如何下載到本機專案(pull
),並且處理可能的檔案衝突,即本機及遠端都有更新內容,但兩者更新的地方不同,而造成要選擇是否保留或刪除該內容的問題。這些就是Git指令的主要任務,其餘較進階的指令,等更熟悉Git指令後,可以再深入學習。
第一次要取得專案內容時,需要將遠端Git專案複製到本機,此時可使用clone
指令。
# 複製專案到本機
git clone https://github.com/user/project.git
而一個基本Git指令的循環,包括pull
及push
指令。將遠端的資料抓到本機,更改後,再傳送到遠端。
# 確認自己目前在哪個分支,以及有哪些本機分支
git branch
# 先拉遠端最新內容,確認是否落後版本或有衝突
git pull origin main
# 查看專案有哪些變更
git status
# 加入特定檔案至暫存區
git add index.html
# 也可以加入全部檔案至暫存區
git add .
# 填寫提交訊息
git commit -m "更新了首頁的內容"
# 發送檔案到遠端
git push origin main
.gitignore
檔案介紹本機有一些環境設定檔案,內容包含一些機敏資料,如帳號密碼、API網址等,這些資料不適合發送到遠端公開,因此在push
之前,通常會先設定.gitignore
檔案,將不想發送到遠端的檔案位置,撰寫到裡面,當push
時,就會自動忽略裡面的檔案,避免機敏資訊外洩。
# .gitignore示例
#frontend
node_proxy/
node_proxy/node_modules/
client/test.http
client/js/env.js
client/js/test.js
client/node_modules/
client/yarn.lock
client/vue.config.js
client/src/common/config.js
client_backup/
而當不小心將不應公開的檔案傳送到遠端時,可以參考以下指令,將遠端的檔案刪除,但不會更動到本機的檔案。
# 可先確認ignore規則是否生效於特定檔案
git check-ignore -v server/envs/dev.env
# 從暫存區移除(但本機檔案會保留)
git rm --cached server/envs/dev.env
# 提交記錄
git commit -m "刪除遠端檔案.env"
# 再次傳送到遠端
git push origin main --force
若要連同本機的檔案一起刪除,就直接刪掉本機的檔案,再傳送一次專案到遠端。
# 刪除本機檔案
rm client/js/wrong_file.js
# 加入暫存區
git add .
# 提交紀錄
git commit -m "刪除錯誤檔案wrong_file.js"
# 傳送到遠端
git push origin main
fetch
+ merge
)pull
指令會直接更新本機檔案,如果在從遠端拉資料前,想先檢查遠端的版本內容是否為自己想要的內容,可先以fetch
指令檢查,以避免直接影響工作檔案,等檢查完成,再以merge
指令合併。
# 從遠端抓最新版本資訊到本機,但不會更改到本機檔案
git fetch
# 檢查遠端與本機檔案的差異
git diff origin/dev_frontend
# 可決定單獨檔案更新
git checkout origin/dev_frontend -- client/src/views/Employee.vue
#或
git restore --source=origin/dev_frontend -- client/src/views/Employee.vue
# 檢查檔案後,決定要合併時,再進行合併
git merge origin/dev_frontend
若想要比對本機檔案與暫存區的差異,或已經執行git add
後,暫存區要與最後一次提交的檔案進行比較,可分別執行以下指令。
# 本機檔案 vs 暫存區
git diff
# 暫存區 vs 最後一次提交(已經git add)
git diff --staged
當遇到衝突時,比較細緻的做法是,先暫存本機檔案,然後再pull
遠端檔案,若有衝突,可以再手動處理
# 暫存特定檔案,-u可將未追蹤的檔案,也一起暫存
git stash push client/src/views/Employee.vue
git stash push -u client/src/views/Employee.vue
# 拉遠端更新檔案,此時可能會有衝突
git pull
# 可先查看暫存內容的差異
git stash list
git stash show -p # 只看最新一筆stash
git stash show -p stash@{0} # 指定看特定一筆stash
# 將暫存區檔案還原(即把stash的變更套回工作目錄)
git stash pop # pop會刪除暫存區的stash,但若有衝突,也不會刪除
#或
git stash apply # apply不會刪除暫存區的stash
# 若僅需要取回暫存區中單一檔案
git checkout stash@{0} -- client/src/views/Employee.vue
#或
git restore --source=stash@{0} -- client/src/views/Employee.vue
# 若有衝突
# 先處理衝突檔案,決定何者的內容要保留或刪除
# 處理完成,加到暫存區,並加註解,傳送檔案到遠端
git add client/src/views/Employee.vue
git commit -m "合併 Employee.vue 並解衝突"
git push
# 處理完成,將stash刪除
git stash drop stash@{0}
衝突解決,也可以針對單獨的commit進行處理,但可能因為修錯單獨的版本,導致日後追蹤修正不易,還是建議以merge針對整個分支一同處理,以下指令僅供參考。
# 切換到要修正的分支
git switch dev_backend
# 只會帶來指定commit的更動,不會帶其他commit
git cherry-pick <commit-hash> # <commit-hash>為commit ID,用git log找
git cherry-pick <hash1> <hash2> <hash3> # 一次挑多筆
git cherry-pick <oldest-commit>^..<newest-commit> # 挑連續區間
# 若發生衝突
# 編輯檔案解衝突
git add <解完衝突的檔案>
git cherry-pick --continue # 繼續處理下一筆
# 內容已存在、套用後變空,會出現empty commit訊息
git cherry-pick --skip # 跳過
# 解到一半,不想解衝突
git cherry-pick --abort # 回到操作前狀態
git cherry-pick --quit # 保留目前衝突狀態,之後可繼續處理
# 驗證與回復
git log --oneline --decorate -n 10
git reset --hard HEAD^ # 撤掉剛剛那一筆
git revert <那筆hash> # 若已經傳送到遠端,則產生反向提交
總算完成30篇文章的撰寫,這一系列的文章,主要是在課堂學習過程中,面對網頁從撰寫、部署到展示之中,所面臨的問題,以及我如何想辦法問出答案的過程的紀錄。對我而言,這是方便日後遇到類似狀況時,能回頭查找並複習解決方法的筆記;但如果這些紀錄也能對剛踏入網頁開發領域的初學者有所幫助,那我將感到非常開心與欣慰。