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