面試只會git clone?git面試都問些啥?這份總結請收好
什么是Git,為什么要用Git等等這些相信看到該標題點進來的同學也不希望浪費時間再看一遍,那么直接進入主題,對于日常工作中常用的Git相關操作進行整理,一起看看吧!
面試官:你常用的Git操作是什么?
候選人:git clone
面試官:還有嗎?
候選人:沒了,我是cv工程師
面試官:好好好這么玩是吧,你最好都能答上來
如何在Git中創建新分支
git branch <branch-name>
該命令會在當前的位置創建一個新分支,但并不會切換到這個新分支。如果希望切換到新創建的分支,可以使用以下命令:
git checkout -b <branch-name>
或者,從Git 2.23版本后,可以使用以下命令來創建并切換到新分支:
git switch -c <branch-name>
也正好可以回答“如何在Git中切換分支”。
如何刪除Git中的分支?
git branch -d <branch-name>
branch-name是待刪除的分支名稱,該命令會刪除本地分支,但如果分支有未合并的更改,Git會拒絕刪除,并提醒先合并或解決沖突。
如果確定要強制刪除分支,包括未合并的更改,可以使用以下命令:
git branch -D <branch-name>
注意,無法刪除主分支、當前所在分支或非分支的內容。
此外,如果想要刪除遠程倉庫中的分支,可以使用:
git push origin --delete <branch-name>
刪除分支后commit會發生什么
(1) 本地分支
如果分支上的所有更改都已經合并到其他分支,那么分支的刪除是安全的,本地分支上的commit歷史將被移除。
如果分支上有未合并的更改,刪除分支時,Git 會阻止刪除,并提醒先合并或處理這些更改。這是為了確保不會意外丟失未合并的工作。
(2) 遠程分支
遠程分支的刪除不會直接刪除分支上的commit,而是在遠程倉庫中標記分支為已刪除。這樣其他協作者可以看到分支已被刪除,但仍然可以在本地找到分支的commit歷史,直到遠程倉庫執行了垃圾回收(garbage collection)來清理這些已刪除的分支。
什么是Git垃圾收集器?
Git 垃圾收集器(Garbage Collector)是一個負責清理不再被引用的 Git 對象的機制。在 Git 中,所有的數據都被存儲為對象,包括提交(commits)、樹對象(trees)、標簽(tags)等。有時候,由于分支切換、分支刪除等操作,一些對象可能變得不再可達,但仍然占用著存儲空間。
Git 垃圾收集器的作用是定期運行,查找那些不再被引用的對象,并將其從 Git 數據庫中刪除,以釋放存儲空間。垃圾收集器有助于保持 Git 倉庫的健康狀態,防止不必要的存儲空間占用。
在日常使用中,大部分情況下,開發者不需要手動觸發 Git 垃圾收集器,因為 Git 會在執行一些操作時自動進行清理。然而,有時可能希望手動運行垃圾收集器,可以使用以下命令:
git gc
git gc 和 git gc --auto 有什么區別?
(1) git gc
手動觸發 Git 垃圾收集器的方式。當運行git gc時,Git 會執行一系列的清理操作,包括垃圾收集和優化存儲等。
(2) git gc --auto
自動垃圾收集。在這種模式下,Git 會自動判斷是否需要運行垃圾收集,如果需要則執行。通常Git 在一些操作(比如commit、merge等)之后會自動檢查并執行垃圾收集,所以大部分時間不需要手動運行 git gc --auto。
git gc --no-prune 的作用是什么?
git gc --no-prune 用于運行 Git 垃圾收集器但不執行實際的對象刪除操作。在正常的 git gc 運行中,Git 會查找不再需要的對象,并將它們從存儲中刪除以釋放磁盤空間。然而,使用 --no-prune 選項,Git 會執行垃圾收集的其他方面,但保留不再需要的對象而不進行刪除。
這個選項有時候可能會用于調試或特定的維護場景,允許查看垃圾收集器標記的對象,但不會真正刪除它們。這樣可以在不改變存儲結構的情況下,查看 Git 認為哪些對象可以被清理。
什么是 git merge?
git merge 是 Git 中用于合并不同分支的命令。將兩個或多個分支的歷史和更改集成到一個新的commit中的過程。合并操作通常用于將一個分支的變更合并到另一個分支,以確保這兩個分支包含了相同的代碼更改:
git merge <branch-name>
將指定分支中的更改合并到當前分支。在執行合并之前,通常需要確保當前分支是要合并的目標分支。
git merge有哪些策略?
(1) Fast-forward Merge
Fast-forward(快進)合并發生在當前分支上沒有新的commit時,當試圖將一個分支合并到另一個分支時,如果沒有需要合并的新commit,Git 可以直接將目標分支指針移動到源分支的位置,而無需創建新的合并commit,舉例說明更清晰。
假設有兩個分支,master 和 feature,并且它們的commit歷史如下:
A---B---C master
\
D---E feature
在這個情況下,在 master 分支執行了 Fast-forward 合并:
# 切換到 master 分支
git checkout master
# Fast-forward 合并 feature 分支
git merge feature
Git 將會簡單地移動 master 指針到 feature 分支的最新commit E 上,形成一個直線式的commit歷史:
A---B---C
\
D---E master, feature
需要注意的是,Fast-forward 合并只能發生在當前分支沒有新commit的情況下。如果有新的commit,Git 將執行普通的三方合并(three-way merge)來創建一個新的合并commit。
(2) Three-way Merge
Three-way merge(三方合并)通常用于解決分支之間存在沖突的情況。這種合并方式涉及三個版本的代碼:兩個分支的最新commit(共同祖先和當前分支的最新commit)以及它們的共同祖先,依舊搭配例子食用。
任然還是master 和 feature分支,commit歷史如下:
A---B---C master
\
D---E feature
執行合并命令:
# 切換到 master 分支
git checkout master
# 合并 feature 分支
git merge feature
Three-way merge會干嘛?Git 會找到兩個分支的最近共同祖先(commit B),以及它們各自的最新commit(commit C 和 commit E):
A---B---C
\ /
D---E master, feature
在這個情況下,Git 將會比較三個版本的代碼(B、C、E),并嘗試合并它們。如果沒有沖突,Git 會自動創建一個新的合并commit,形成一個合并后的commit歷史:
A---B---C---F master
\ / /
D---E feature
如果合并過程中存在沖突,Git 將會標記,等待用戶手動解決。用戶解決沖突后,再執行 git merge --continue 來完成合并。
講完了兩種merge策略,怎么人為指定哪個合并策略?
git merge --no-ff <branch-name>
--no-ff 選項用于強制創建一個新的合并commit,即使可以執行快速前進合并,這樣可以保留每個分支的獨立歷史。
要執行Fast-forward 合并,則:
git merge --ff <branch-name>
合并提交(Merge Commit)和常規提交(Regular Commit)有什么區別?
(1) Merge Commit
由 git merge 命令創建,用于合并分支,通常會產生一個新的合并節點,有兩個或多個父commit。
(2) Regular Commit
由 git commit 命令創建,記錄了在當前分支上的一次更改,產生一個普通節點,只有一個父commit。
如何撤消 git commit ?
可以使用git reset,git reset 命令允許將當前分支的 HEAD 指針移動到不同的位置,有三個主要的選項:--soft、--mixed 和 --hard,對應于不同的重置模式。
(1) git reset --soft
git reset --soft <commit>
回退 HEAD 指針到指定的commit,但保留所有的更改。即不會修改工作目錄或暫存區,所有的更改都被標記為未commit的更改,可以直接重新commit。
(2) git reset --mixed
git reset --mixed <commit>
默認的reset模式。回退 HEAD 指針到指定的commit,并且重置暫存區,但保留工作目錄中的更改。即未commit的更改會保留在工作目錄,但不會被標記為暫存區的更改,需要重新add并commit。
(3) git reset --hard
git reset --hard <commit>
最徹底的reset模式。回退 HEAD 指針到指定的commit,重置暫存區,并刪除工作目錄中未commit的更改,慎用這個玩意,因為它會永久性地刪除未commit的更改。
git reset 和 git revert 有什么區別?
(1) git reset
用于將分支的 HEAD 指針和工作目錄重置到指定的commit,可以選擇是否保留未commit的更改,主要用于本地分支上的操作,慎用于已推送到遠程倉庫的分支,以免引起沖突:
git reset --soft HEAD^ # 保留未commit的更改,將這些更改標記為暫存區的更改,不修改工作目錄
git reset --mixed HEAD^ # 默認模式,將未commit的更改標記為未暫存區的更改,不修改工作目錄
git reset --hard HEAD^ # 丟棄未commit的更改,重置暫存區和工作目錄到指定的commit
(2) git revert
創建新的commit,撤銷指定commit及其之后的更改,而不修改commit歷史,適用于已經推送到遠程倉庫的commit,避免修改歷史引起問題:
git revert HEAD # 撤銷最后一次commit
git revert <commit-hash> # 撤銷指定commit
Git 中的暫存是什么?
在Git中,"暫存"(Staging)指的是將工作目錄中的修改或新文件添加到Git的索引中(也稱為暫存區),以便隨后commit這些更改。暫存的主要目的是允許選擇性地commit文件而不是全部文件的修改,一般的步驟為:
(1) 修改文件:在工作目錄中對文件進行修改
(2) 將修改添加到暫存區
git add 文件名
(3) commit到Git倉庫
git commit -m "description"
通過使用暫存區,可以控制哪些修改被包含在下次commit中,從而更加靈活地管理項目的版本歷史。
git rebase 是什么?
git rebase 是 Git 中用于合并分支的一種方式,它與 git merge 類似,但有一些重要的區別。
在使用 git rebase 時,通常會選擇一個基礎分支(base branch)和一個目標分支(target branch)。基礎分支上的commit將被移至目標分支上,這個過程涉及到逐個應用commit,因此它會改寫commit歷史:
git rebase <base-branch>
同樣以例子來說明,假設我們有兩個分支,main 和 feature,它們的commit歷史如下:
A---B---C main
/
D---E---F---G feature
在這個例子中,我們希望將 feature 分支上的commit整合到 main 分支上。
執行 git checkout main 切換到 main 分支,然后執行 git rebase feature:
git checkout main
git rebase feature
這將會創建一個新的commit歷史:
A'--B'--C' main
/
D---E---F---G feature
A'、B' 和C' 通過逐個應用 feature 分支上的commit得到,這是 git rebase 的基本工作方式。
要注意的是,原來的E 、 F、G 并沒有被修改,它們保留在歷史中。新的commit A'、B' 和 C' 被創建,并在 main 分支上形成了一個更加線性的歷史。
沒明白的可以參考:;https://git-scm.com/docs/git-rebase。
- git merge 通過多次合并commit生成更全面、更易讀的歷史記錄,如果兩個分支有沖突,Git 會生成一個合并commit,需要手動解決沖突
- git rebase 通過更少的commit創建更清晰、線性的歷史記錄,在 rebase 過程中,如果有沖突,Git 會逐個應用commit并在每個沖突點停下,需要手動解決沖突,然后繼續 rebase。該方式更容易引入風險,因為會修改commit歷史,可能導致沖突或數據丟失。
git tag 作用?
git tag 用于給 Git 中的commit打上標簽(tag),這些標簽通常用于標識某個特殊的commit,比如軟件版本發布。標簽提供了一個穩定的引用,使得方便地回溯到某個特定的commit,常用的命令選項有
- -a:用于創建一個帶注釋的標簽
- -m:指定標簽的注釋信息
- -l:列出已有的標簽
git tag -a v1.0 -m "Version 1.0 release"
列出所有tag:
git tag
列出匹配條件下的tag:
git tag -l "v1.*"
git stash 是什么?
git stash 是一個用于保存當前工作目錄和暫存區的臨時狀態的命令。允許在切換分支、應用補丁或執行其他操作之前,將當前的修改存儲起來,以便稍后重新應用,非常非常實用,常見的使用場景如:
(1) 保存當前工作目錄和暫存區的狀態
git stash save "Work in progress"
(2) 切換到其他分支進行操作
git checkout other-branch
(3) 在其他分支進行操作
# 在 other-branch 上進行一些操作
(4) 切回原始分支并恢復 stash
git checkout original-branch
git stash apply
或者,如果想同時刪除 stash,可以使用:
git stash pop
此外,還有一些其他常用命令:
git stash list # 顯示 Git 存儲庫中所有存儲的列表,以及有關每個存儲的一些信息
git stash branch <branch-name> # 將更改應用到不同的分支
git cherry-pick 有什么作用?
git cherry-pick 將指定的commit復制到當前分支,創建一個新的commit,但不會將整個分支合并過來。通常用于在不合并整個分支的情況下引入或應用特定的更改:
git cherry-pick <commit-hash> # <commit-hash> 是要應用的commit的哈希值
git pull 和 git fetch 之間有什么區別?
git pull 和 git fetch 都是用于從遠程倉庫獲取更新的 Git 命令,但區別為:
(1) git fetch
git fetch origin
從遠程倉庫獲取更新的信息,但并不自動合并或更新本地工作目錄, 只是把遠程分支的引用和相關對象(commit、tree等)下載到本地,需要手動合并或者在需要的時候將遠程分支的變更整合到本地分支上。
(2) git pull
git pull origin master
- 從遠程倉庫獲取更新的信息,并嘗試將本地工作目錄自動合并到獲取的更新中
- git pull 實際上包含了 git fetch,比如在執行 git fetch 之后,立即執行 git merge 也可以將遠程分支的更改合并到當前本地分支
面試官:好好好,你tm裝13是吧