git push === ###### tags: `git`, `gitlab`, `git-lab`, `github`, `git-hub`, `push` <br> [TOC] <br> ## 常見 Q & A ### 為什麼 `git push` 會失敗(non-fast-forward)? > by gpt-5.2 (2026/02/02) ``` $ git push To ssh://10.0.1.2:30000/my-project/my-service.git ! [rejected] main -> main (non-fast-forward) error: failed to push some refs to 'ssh://10.0.1.2:30000/my-project/my-service.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. If you want to integrate the remote changes, hint: use 'git pull' before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details. ``` - A:因為遠端 `origin/main` 比你本機多 commit,你本機又先做了 commit。此時直接 push 會被拒絕,必須先把遠端更新整合進來(pull/rebase)再推。 - ### Q: `git pull` ``` $ git pull hint: You have divergent branches and need to specify how to reconcile them. hint: You can do so by running one of the following commands sometime before hint: your next pull: hint: hint: git config pull.rebase false # merge hint: git config pull.rebase true # rebase hint: git config pull.ff only # fast-forward only hint: hint: You can replace "git config" with "git config --global" to set a default hint: preference for all repositories. You can also pass --rebase, --no-rebase, hint: or --ff-only on the command line to override the configured default per hint: invocation. fatal: Need to specify how to reconcile divergent branches. ``` 為什麼 `git pull --rebase` 說我有 unstaged changes? - A:因為你工作區有未提交的修改(例如 `config/slurm.key`)。Rebase 需要工作區乾淨,所以要先 **stash** 或 **丟掉變更**。 - ### Q:最簡單的標準解法(保留本機修改、不提交它)怎麼做? - A:用 stash → rebase → push → stash pop ```bash git stash -u git pull --rebase git push git stash pop ``` - `-u`, `--include-untracked`, `--no-include-untracked` When used with the push and save commands, all untracked files are also stashed and then cleaned up with git clean. > **搭配 `push` 與 `save` 指令使用時**:會把**所有未追蹤檔案(untracked files)**也一併加入 stash,並且接著透過 `git clean` 將這些未追蹤檔案**清理掉**。 When used with the show command, show the untracked files in the stash entry as part of the diff. > **搭配 `show` 指令使用時**:會在 diff 的內容中,將 stash 項目裡的**未追蹤檔案**也一併顯示出來。 - ### Q:如果我不想保留本機那個修改(直接放棄)? - A:先丟掉變更,再 rebase/push ```bash git restore <檔案> git pull --rebase git push ``` (例:`git restore config/slurm.key`) - ### Q:我不想讓某個「本機專用檔」每次都出現在 `git status`? - A:用 `skip-worktree` 讓它保持本機差異、但不再一直提示 ```bash git update-index --skip-worktree <檔案> ``` 要取消: ```bash git update-index --no-skip-worktree <檔案> ``` - ### Q6:`docs/debug/`、`__pycache__/` 這種檔每次都出現很煩,怎麼辦? - A:加到 `.gitignore` ```gitignore docs/debug/ __pycache__/ ``` <br> ## 討論 ### fatal: You are not currently on a branch. - ### Question ``` $ git push fatal: You are not currently on a branch. To push the history leading to the current (detached HEAD) state now, use git push origin HEAD:<name-of-remote-branch> ``` 原本 git push 就可以 commit ,為何變成這樣? - ### gpt-4.1 (2025/08/08) 你出現「fatal: You are not currently on a branch」 這表示**你目前在 detached HEAD 狀態**,不是在任何本地分支上,所以 git 不知道要把 commit 推到哪一個分支。 --- ### 為什麼會發生? 常見原因有: * 你是用 `git checkout origin/xxx`(帶上遠端分支名稱)而不是 `git checkout xxx`(本地分支名稱),這會讓 HEAD 指到某個 commit,而不是分支頭。 * 或你用 `git checkout <commit-sha>`,直接進入 detached HEAD 狀態。 --- ### 怎麼解決? **1. 檢查目前狀態** ```bash git status ``` 你會看到類似: ``` HEAD detached at <commit-sha> ``` --- **2. 重新切回本地分支再 push** 假設你本來要 push 到 `master`: ```bash git checkout master git pull # 先同步遠端,避免衝突 git push ``` 如果你是要 push 到 `claude/issue-55-d23bc`: ```bash git checkout claude/issue-55-d23bc git pull git push ``` --- **3. 如果本地沒有那個分支,建立本地分支繼續操作** 假設你在 detached HEAD 狀態, 你可以用下面的指令讓你的當前內容變成一個本地分支,然後再 push: ```bash git checkout -b my-temp-branch git push origin my-temp-branch ``` --- ### 為什麼原本 git push 可以、現在不行? * **原本你在分支上**(如 `master`),`git push` 會自動推到對應的遠端分支。 * **現在你在 detached HEAD 狀態**,沒有任何分支對應,`git push` 不知道你想推去哪。 * 只要回到分支(`git checkout <branch>`),就會恢復正常。 --- ### 總結 * 解法:**切回你的本地分支再 push** * 或用 `git checkout -b <new-branch>` 再 push --- 你要不要貼一下 `git status` 給我看? 可以幫你分析是從哪個 commit / 分支進到 detached HEAD 的! <br> ### detached HEAD 怎麼用中文稱呼? - ### gpt-4.1 (2025/08/08) 「detached HEAD」在中文(尤其是臺灣地區工程師常用語境)通常會翻譯成: * **分離 HEAD 狀態** * **游離 HEAD 狀態** * **HEAD 游離狀態** * **HEAD 已分離** 其中最常見、最普遍被接受的說法是: > **分離 HEAD 狀態** > (英文:detached HEAD state) 或簡稱「**分離 HEAD**」、「HEAD 分離狀態」。 --- ### 範例說明 * 你現在是在**分離 HEAD 狀態**,無法直接 push 到遠端分支。 * Git 會顯示「分離 HEAD」或「HEAD 已分離」提示。 --- ### 臺灣社群用法 多數教學、書籍、社群討論也都直接寫「分離 HEAD 狀態」。 (有時候保留英文 detached HEAD,因為很難誤解。) --- 如需對一般使用者解釋,可以補充: > 「分離 HEAD」指的是目前不是位於任何分支,而是直接在某個 commit 上操作的狀態。 --- 有需要更多簡單白話的解釋範例,也可以再問我! <br> {%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}