Site icon May's Notes

Git 常見指令筆記和Q&A

git

git log

用於查看最新 commit 紀錄,可指定顯示的筆數。

git log --oneline -<number>

# 能顯示多少條就顯示多少條
git log --oneline
# 只顯示最新五條
git log --oneline -5

顯示結果:

# $git log --oneline -5
e295702 (HEAD -> main) A
21582f6 B
79e280f C 
b51ec3b D
ad7f577 E

q 離開 git log

基本指令

# 查看 remote 
git remote -v
# 新增 remote repo
git remote add origin <repo>
# 查看當前 working tree
git status
# 新增全部 changes 到暫存區
git add .
# 將暫存區的 changes 提交
git commit -m "msg"
# 將 commit 推上 remote repo,分支名稱為 <branch_name>
git push origin <branch_name>

git branch

# 列出分支列表
git branch -a
# 新增
git branch A
# 刪除本地分支
git branch -d A
# 刪除遠程分支
git push origin --delete A
# 切換
git checkout A

git merge

git merge 用於將 A 分支上的修改合併到 B 分支。

假設要將分支 A 的修改合併到分支 develop 可以這麼操作:

git checkout A
git add .
git commit -m "test"

git checkout develop
git merge A

快轉模式(Fast-forward)

快轉模式合併是 Git 中的一種合併策略(也是預設的模式),它通常發生在以下情況:

在這種情況下,Git可以簡單地將目標分支 HEAD 前進到與您目前分支的最新提交相同的地方,而不需要建立一個新的 commit。

特性包括:

  1. 不會建立新的合併提交,因為沒有衝突需要解決。
  2. 歷史記錄看起來非常線性,就好像沒有進行合併操作一樣。
  3. 通常用於將特性分支的變更合併到主分支,以保持主分支的更新。

舉例來說,現在 dev 分支 HEAD 在 c4,而 master 分支的 HEAD 在 C2。
此時我們可以透過 git merge 的方式將 master 的 HEAD 前進到 C4,並且不需要新增額外的合併 commit。

git checkout master
git merge dev

git rebase

和 git merge 類似都是合併操作,但 git rebase 會修改歷史 commit,它會使分支移動到不同的 Commit 重新定義基準點。

合併版本

git checkout branch1

# 將 mater 當成基準點
git rebase master

當基準點改變就需要重新生成 commit 的 SHA-1 值,所以原本的 e3475, 76d12 在修改基準點後變成了 3a2e2, e45ch

修改歷史 commit

$ git rebase -i HEAD~3

取消 rebase 操作

git rebase 指令會導致 Commit 的 SHA-1 值改變,因此不能直接使用 git reset HEAD^–hard 的方式回到合併前的狀態。

需要先使用 git reflog 找回 rebase 操作時 commit 的 SHA-1 值,找到後再使用 git reset <commit> --hard 回到 rebase 前的狀態。

# $git reflog
...
153ab21 (master) HEAD@{3}: rebase: checkout master
b274b5a HEAD@{4}: checkout: moving from master to branch1
...

# $git reset b274b5a --hard
HEAD is now at b274b5a

或者也可以直接使用 git reset ORIG_HEAD --hard 回到 rebase 前的狀態。

ORIG_HEAD 會記錄「危險操作」之前 HEAD 的位置。例如分支合併或是 Reset 之類的都算是所謂的「危險操作」。

git revert & git reset

revert

revert 是在「不破壞歷史紀錄」的前提下撤回指定 commit。

以下方 commit 紀錄為例,指令 git revert HEAD~2 會撤回 study 的這個 commit 紀錄,並新增一個 commit Revert "study"

# git log --oneline
c0479f5 (HEAD -> main) day
0199749 study
0a38bea third
1ae88ed second
fa3d5af first

# git revert HEAD~

# git log --oneline
fd5db43 (HEAD -> main) Revert "study"
c0479f5 day
0199749 study
0a38bea third
1ae88ed second
fa3d5af first

如果想回到撤回 study 之前,直接 git reset --hard c0479f5,這樣 study 就回來了

reset –hard

git reset --hard

# 回到 HEAD 的前 1 個版本 commit 
git reset --hard HEAD~
# 回到 HEAD 的前 2 個版本 commit 
git reset --hard HEAD~2
# 回到 HEAD 的前 3 個版本 commit 
git reset --hard HEAD~3
...

以下面的 commit 紀錄為例:

# $git log --oneline -5
e295702 (HEAD -> main) A
21582f6 B
79e280f C
b51ec3b D
ad7f577  E

不小心使用 hard 模式 Reset 了某個 Commit,救得回來嗎?

  1. git log --oneline 查看 commit 紀錄
c0479f5 (HEAD -> main) day
0199749 study
0a38bea third
1ae88ed second
fa3d5af first
  1. git reset --hard HEAD~2 回到前 2 個版本,log紀錄少了 0199749, c0479f5
0a38bea (HEAD -> main) third
1ae88ed second
fa3d5af first
  1. git reset --hard <commit id> 就可以恢復被 reset 過的 commit
c0479f5 (HEAD -> main) day
0199749 study
0a38bea third
1ae88ed second
fa3d5af first

只需要記住 commit SHA-1 就可以將 HEAD 重新設回被 reset 過的 commit,完整流程如下:

# $git log --oneline
c0479f5 (HEAD -> main) day
0199749 study
0a38bea third
1ae88ed second
fa3d5af first

# $git reset --hard HEAD~2
HEAD is now at 0a38bea third

# $git log --oneline
0a38bea (HEAD -> main) third
1ae88ed second
fa3d5af first

# $git reset --hard c0479f5
HEAD is now at c0479f5 day

# $git log --online
c0479f5 (HEAD -> main) day
0199749 study
0a38bea third
1ae88ed second
fa3d5af first

找回 commit SHA-1 值

可以使用 git reflog

HEAD 有移動的時候就會紀錄(切分支或者reset都會移動HEAD),可以在這裡查看 reset 之前的 commit SHA-1:

0a38bea HEAD@{1}: reset: moving to HEAD~2
c0479f5 (HEAD -> main) HEAD@{2}: commit: day
0199749 HEAD@{3}: commit: study
0a38bea HEAD@{4}: commit: third
1ae88ed HEAD@{5}: commit: second
fa3d5af HEAD@{6}: commit (initial): first

git reset --hard c0479f5 就可以回到 reset HEAD~2 前的 HEAD

git cherry-pick

可以選擇並將指定的 commit 從一個分支應用到另一個分支。

git cherry-pick <commit-hash>

git cherry-pick 對於以下情況很有用:

  1. 合併特定的 commit:選擇合併一個或多個 commit,而不是將整個分支合併到目前分支。
  2. 修復錯誤:如果在一個分支上發現了錯誤,而這個錯誤在另一個分支上已經修復就可以用 git cherry-pick 來將修復的 commit 引入到當前分支,而無需合併整個分支。

Q&A

正在重訂基底

這表示 Git 正在進行 rebase 操作(git rebase)。

解決方式

  1. 強制退出:執行 git rebase --abort 終止 rebase,這將會復原分支到 rebase 開始前的狀態。
  2. 完成rebase:解完 conflicts -> git add & git rebase --continue -> 繼續解直到沒有 conflicts -> git push

fatal: not a valid object name: ‘main’

可能是因為新 repo 沒有文件所導致的。

解決方式

# 新增文件
git add .
git commit -m "log"

git branch -a 
# 這時候就會出現 main 分支了

You have divergent branches and need to specify how to reconcile them

git push 失敗

git pull 失敗

這是因為 pull 分支之前進行過 merge 合併更新分支操作,而其他人在你之前已經 push 過一個版本,導致版本不一致。

解決方式git config pull.rebase false

skipped previously applied commit xxx

skipped previously applied commit xxx
hint: use --reapply-cherry-picks to include skipped commits. 
hint: Disable this message with "git config advice.skippedCherryPicks false"

解決方式git rebase --reapply-cherry-picks

git rebase –continue: Please enter the commit message for your changes

git rebase --continue 出現:

feat: A

# Please enter the commit messagefor your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# interactive rebase in progress; onto 16832f7
# Last command done (1 command done):
#    pick 7b45117 feat: A
# Next commands to do (5 remaining commands):
#    pick 474bdfd B
#    pick 58b9193 C
# You are currently rebasing branch 'feat/demo' on '16832f7'.
#
# Changes to be committed:
#       ....

解決方式::wq 退出

Reference

Exit mobile version