05 - Push 與 Pull
← 04-GitHub入門 | 下一篇 → 06-分支管理
⬆️ Push:把本地推到 GitHub
# 第一次 push(需要設定 upstream)
git push -u origin main
# 之後每次 push 只需要
git push
-u是--set-upstream的縮寫,設定預設的推送目標。 第一次設定後,以後直接git push就夠了。
完整的第一次 push 流程
# 1. 初始化(如果還沒有)
git init
# 2. 加入所有檔案
git add .
# 3. 建立第一個 commit
git commit -m "Initial commit"
# 4. 連接 GitHub repo
git remote add origin git@github.com:username/repo-name.git
# 5. Push!
git push -u origin main⬇️ Pull:從 GitHub 拉下最新版本
git pullgit pull 實際上是兩個指令的組合:
git fetch ← 從 GitHub 抓取最新資料(但不合併)
+
git merge ← 將抓下來的內容合併到本地
什麼時候要 pull?
- 在多台電腦上工作時,每次開始工作前先 pull
- 和別人合作時,在 push 之前先 pull
🔄 多台電腦的同步工作流程
電腦 A(家裡)完成工作後:
git add .
git commit -m "更新筆記"
git push電腦 B(醫院)開始工作前:
git pull
# 現在就有最新的筆記了,可以繼續編輯⚠️ Push 被拒絕怎麼辦?
最常見的錯誤訊息:
! [rejected] main -> main (fetch first)
error: failed to push some refs
這代表 GitHub 上有你本地沒有的新 commit(例如在另一台電腦 push 過)。
解法
# 先 pull(把遠端的拉下來合併)
git pull
# 確認沒有衝突後,再 push
git push🔁 git pull —rebase:更乾淨的拉取方式
預設的 git pull = fetch + merge,每次遇到遠端有新東西就會多一個 merge commit,
歷史會變得很雜(一堆 Merge branch 'main'...)。
git pull --rebase 改用 rebase 整合:把你本地的 commit「先收起來,套上遠端最新版,再把你的 commit 一個個重放上去」,
歷史是一條乾淨的直線,不會多 merge commit。
# 拉取並用 rebase 方式整合(推薦在自動同步環境用)
git pull --rebase origin main什麼時候特別該用 --rebase?
當 repo 有背景自動同步(例如 obsidian-git 外掛每 10 分鐘自動 push), 遠端
main隨時可能多出新 commit。push 前先git pull --rebase可以避免每次都產生 merge commit、 也降低衝突機率。完整實戰見 09-實戰工作流範例。
設定成預設行為(選用)
# 讓以後的 git pull 預設就用 rebase
git config --global pull.rebase trueRebase 過程中撞到衝突怎麼辦?
# 1. Git 會停下來告訴你哪個檔案衝突
# 2. 手動編輯解決衝突(刪掉 <<<<<<< ======= >>>>>>> 標記)
# 3. 把解決好的檔案加回暫存區
git add 衝突的檔案
# 4. 繼續 rebase(注意:不是 commit!)
git rebase --continue
# 如果想放棄整個 rebase、回到原狀
git rebase --abort💥 Merge Conflict(合併衝突)
如果兩邊都修改了同一個檔案的同一個地方,Git 就不知道要保留哪個版本,會出現衝突。
CONFLICT (content): Merge conflict in notes.md
Automatic merge failed; fix conflicts and then commit the result.
Git 會在衝突的地方標記:
<<<<<<< HEAD
這是你本地的版本
=======
這是 GitHub 上的版本
>>>>>>> origin/main
解決衝突的步驟
- 打開衝突的檔案,手動選擇要保留的內容(刪掉
<<<<<<<、=======、>>>>>>>這些標記) - 存檔
git add 衝突的檔案git commit -m "解決合併衝突"git push
實際走一遍:一個 conflict 的完整解法
假設你和遠端都改了 notes.md 的同一行,pull 後打開檔案看到:
## 治療
<<<<<<< HEAD
第一線用 drug A,劑量 5 mg。 ← 你本地寫的
=======
第一線用 drug A,劑量 10 mg。 ← 遠端(GitHub)的版本
>>>>>>> origin/main
你要親自判斷哪個對(或兩個都要),把整段改成最終想要的樣子,
連同 <<<<<<<、=======、>>>>>>> 三行標記全部刪掉:
## 治療
第一線用 drug A,劑量 10 mg。
然後:
# 先確認還有沒有別的檔案也在衝突
git status # 紅字 "both modified" 就是還沒解的
# 解完所有衝突後,加回暫存區
git add notes.md
# 完成合併
git commit -m "解決 notes.md 劑量衝突"
git push三個實用招式
- 想看「衝突前」雙方各自的版本:
git log --merge -p notes.md- 這次合併太亂、想整個放棄重來:
git merge --abort(回到 pull 之前的狀態)- 用編輯器的合併工具:VS Code 打開衝突檔會有「Accept Current / Incoming / Both」按鈕,比手刪標記更直覺。
解衝突 = 你在做決定
Git 無法替你判斷醫學內容哪個對。絕對不要無腦選一邊或亂刪, 尤其是別人(或自動同步)寫的內容,務必逐行確認再保留。
🔐 HTTPS vs SSH:兩種連線方式怎麼選?
連 GitHub 有兩種 URL 格式,決定了你怎麼驗證身份:
| HTTPS | SSH | |
|---|---|---|
| URL 長相 | https://github.com/user/repo.git | git@github.com:user/repo.git |
| 驗證方式 | Personal Access Token(當密碼) | SSH 金鑰對 |
| 第一次設定 | 簡單,貼 URL 就能 clone | 要先產生並上傳 SSH key |
| 之後每次 push | 需 token(可用 credential helper 記住) | 不用再輸入任何東西 |
| 公司防火牆 | 通常都通(走 443 port) | 有些網路會擋 22 port |
| 推薦對象 | 偶爾用、或網路受限環境 | 自己常用的主力機器 |
Token 認證(HTTPS 用)重點
GitHub 自 2021 年起不接受帳號密碼,HTTPS push 時的「密碼」欄位要填 Personal Access Token (PAT):
# push 時會跳出
Username: 你的 GitHub 帳號
Password: 這裡貼 PAT(不是你的登入密碼!)- 產生 PAT:GitHub → Settings → Developer settings → Personal access tokens(細節見 04-GitHub入門)。
- 至少要勾
repo權限;token 只會顯示一次,當下就複製存好。 - 讓 git 記住 token,不用每次貼:
git config --global credential.helper osxkeychain # macOS git config --global credential.helper manager # Windows git config --global credential.helper store # Linux(明碼存檔,注意安全)
兩種方式互換
# 查目前用哪種
git remote -v
# 把 HTTPS 換成 SSH
git remote set-url origin git@github.com:user/repo.git
# 把 SSH 換回 HTTPS
git remote set-url origin https://github.com/user/repo.git🗑️ 強制覆蓋遠端(危險!謹慎使用)
# 強制 push,會覆蓋遠端的版本
git push --force只在你確定遠端的版本不重要時才使用。
多人協作時絕對不要用,會讓別人的工作消失!
📌 小結
| 指令 | 用途 |
|---|---|
git push -u origin main | 第一次 push(設定 upstream) |
git push | 之後的 push |
git pull | 從 GitHub 拉取最新版本 |
git fetch | 只抓取,不合併 |
← 04-GitHub入門 | 下一篇 → 06-分支管理
