原來是 Git 是時光機

Chloe Lo
chloelo925
Published in
6 min readNov 5, 2020

可惜不能傳送人 (欸) 之版控很重要

Photo by Pankaj Patel on Unsplash

在工程師亦或是設計師的領域,版本控制是相當重要的技術,從前檔案備份都是 v1.0, v-2.0, …v-final-0, v-final-2...說是最終版也還是一直改,心裡 os: 再騙阿,說不會改還一直改,欺騙我感情 (誤),光看檔名也不知道內容到底改了什麼,檔案打開來比對也要找很久,為了讓世界更美好,懶惰是造就工程師發明更好工具的動力,好了~別催,我前言結束。

因為自己是金魚腦,學了一點新東西,三天沒碰可能就忘記,所以來筆記粗略的 Git 要怎麼使用。(會陸續補充,先掌握 5% 最基本也最重要的指令)

Git 中文版練習工具推薦:
https://learngitbranching.js.org/?locale=zh_TW

起手式

VSCode 可以用快捷鍵 ctrl + ` 快速開啟 git 控制面板。

設定使用者 (user) 帳號和信箱

git config --global user.email "xxx@gmail.com"git config --global user.name "chloe"

檢查是否設定成功 — git config — list

常用的基本指令:

  • 新增資料夾 — 假設新增一個 project-demo 的資料夾 mkdir project-demo
  • 進入資料夾 cd project-demo
  • Git 初始化 (安裝數據庫)git init
  • 新增檔案 — 假設新增首頁 index.html 檔touch index.html
  • 加入索引值git add . 點 (.) 指全部檔案都加入 (通常用點就好,比較快速,也可指定單一檔案加入 → 在 add 後方寫入檔名即可)
  • 查看狀態 git status or git st
  • 新增 commit 紀錄
    git commit -m '建立 index.html' or 縮寫 git ci -m '建立 index.html'
  • 查詢 commit 紀錄 git log
  • 在 Github 新增遠端數據庫,本地端連結到遠端
    git remote add origin git@github.com:帳號名/遠端數據庫名.git
  • 把本地端資料推送到遠端數據庫 git push -u origin master

分支 (branch)

建立分支 (git branch)

版本控制預設都會有個主線 master (Github 近期主線預設名改成 main,詳情可點此查看), 主線通常是最終上線版本,在新增修改編輯的時候,不會直接動到最終版本,一定會開分支去操作,確定都沒問題再合併到主線上,所以分支概念很重要。

  • 新增分支 — 假設新增一個 dev (develop,表示開發中) 的分支
    git branch dev
  • 切換分支— 切到分支 dev git checkout dev

合併分支 (git merge)

在分支上完成 commit 之後,目前分支上的版本已經比主線版本還要新,確認分支沒問題後,我們要 (HEAD) 回到主線,合併分支,讓主線與分支同步都是最新版。

  • 切換分支 —回主線git checkout master
  • 合併分支 git merge dev

合併分支 (快轉模式)

過程中,若 master 沒有任何更新,表示初始 commit 位置沒有變動,此時用 master 去 merge dev 就會觸發快轉模式。

合併分支 (非快轉模式)

可以特別強制不要快轉模式,這樣 master 即使沒更新,合併 dev 時也會有 commit 紀錄。
git merge 分支名稱 — no-ff 取消快轉,用意是希望知道在哪個時機點 merge 了

本地分支衝突

並非每次分支合併都會一帆風順,如果剛好不同協作者合併內容同時修改到同一行 CODE 時,就會導致衝突。
解法:彼此要溝通,看最終要用哪個版本 XD

分解衝突流程

  1. git merge dev
  2. 發生衝突,用 git status 查看狀態,衝突的地方狀態會是 Unmerged
  3. 修改確認衝突的地方,重新加入索引 git add <原衝突的檔名>
  4. 再一次 git commit 完成合併

遠端協作分支衝突

本地端 push 到遠端時,如果有衝突,git 會要求你先把遠端的資料 pull 下來,然後解決衝突後再 git add . git commit,再次 push 回遠端,會產生新的兩個 commit 紀錄,衝突的 commit 和解決衝突後合併的 commit。

指令回顧:

  • 建立分支:git branch <分支名稱>
  • 切換分支:git checkout <分支名稱>
  • 合併分支:git merge <分支名稱>
  • 合併分支(取消快轉):git merge 分支名稱 — no-ff

還原版本 (git reset)

總是會有 commit 之後又反悔,覺得之前版本寫得比較好的狀況,這時候還原就很重要了,Git 就好比時光機器,能讓你來回穿梭。

情境:假設現在有三個 commit 紀錄,我要回到第一個 commit

  • 還原到第一個 commit,檔案想保留:git reset HEAD^^
  • 還原到第一個 commit,檔案不想保留:git reset HEAD^^ --hard

--hard 是 reset 的其中一個參數,表示在還原過程中,commit 裡面的檔案都要捨棄時,就可使用。

HEAD 也就是目前指標位置,^就是向前一個版本,,兩個 ^^ 就是向前推兩個版本,除此之外,用 ~ 也可以。如 git reset HEAD~~,如果向前推進的版本很多,也可以用數字取代,如git reset HEAD^2

所以 git reset HEAD^2 等於 git reset HEAD~~

還原大絕招 (git reflog)

假使我們用了 git reset 語法,將版本還原到前面的版本,用 git log 上看也看不到那些紀錄。但此時你又想把 commit 救回來該怎麼辦?

在 git 裡的有些指令會讓你以為檔案不見 (被刪除) 了,但其實只是隱藏到你肉眼看不到的地方,用 git reflog 指令可以把所有看似被刪掉的 commit 都顯示出來,只要找的到 commit 上面的 SHA-1 值 (表 commit 上一長串英文與數字的代碼組合),就可以把 commit 給救回來。

from 六角學院 Git & GitHub 教學手冊

補充觀念:

  • 遠端下載到本地端 pull
  • 本地端到遠端 push
  • 遠端到遠端 PR (pull request)

git clonegit pull 的差別在那邊?

clone 是複製一份下來,用於本地沒有專案時。
pull是從遠端數據庫更新資料下來,是專案已經成立的狀態。

參考資料來源:

  1. 六角學院 - Git & GitHub 教學手冊
  2. 高見龍 @ 五倍紅寶石 — 為你自己學 Git

--

--