天天看點

Java面試題Git篇

作者:CameSawConquer

1、Git和SVN有什麼差別?

Git SVN
1、Git是一個分布式的版本控制工具 1、SVN是幾種版本控制工具
2、它屬于第3代版本控制工具 2、它屬于第2代版本控制工具
3、用戶端可以在其它系統上克隆整個存儲庫 3、版本曆史記錄存儲在伺服器端存儲庫中
4、即使離線也可以送出 4、隻允許線上送出
5、push/pull操作更快 5、push/pull操作更慢
6、工程可以用commit自動共享 6、沒有任何東西自動共享

2、什麼是Git?

我建議你先通過了解 git 的架構再來回答這個問題,如下圖所示,試着解釋一下這個圖:

  • Git 是分布式版本控制系統(DVCS)。它可以跟蹤檔案的更改,并允許你恢複到任何特定版本的更改。
  • 與 SVN 等其他版本控制系統(VCS)相比,其分布式架構具有許多優勢,一個主要優點是它不依賴于中央伺服器來存儲項目檔案的所有版本。
  • 每個開發人員都可以“克隆”我在圖中用“Local repository”标注的存儲庫的副本,并且在他的硬碟驅動器上具有項目的完整曆史記錄,是以當伺服器中斷時,你需要的所有恢複資料都在你隊友的本地 Git 存儲庫中。
  • 還有一個中央雲存儲庫,開發人員可以向其送出更改,并與其他團隊成員進行共享,如圖所示,所有協作者都在送出更改“遠端存儲庫”。
Java面試題Git篇

3、在 Git 中送出的指令是什麼?

答案非常簡單。 用于寫入送出的指令是 git commit -a。

現在解釋一下 -a 标志,

通過在指令行上加 -a 訓示 git 送出已修改的所有被跟蹤檔案的新内容。

還要提一下,如果你是第一次需要送出新檔案,可以在在 git commit -a 之前先 git add 。

4、什麼是 Git 中的“裸存儲庫”?

你應該說明 “工作目錄” 和 “裸存儲庫” 之間的差別。

Git 中的 “裸” 存儲庫隻包含版本控制資訊而沒有工作檔案(沒有工作樹),并且它不包含特殊的.git 子目錄。相反,它直接在主目錄本身包含 .git 子目錄中的所有内容,其中工作目錄包括:

  • 1. 一個 .git 子目錄,其中包含你的倉庫所有相關的 Git 修訂曆史記錄。
  • 2. 工作樹,或簽出的項目檔案的副本。

5 Git 是用什麼語言編寫的?

你需要說明使用它的原因,而不僅僅是說出語言的名稱。我建議你這樣回答:Git使用 C 語言編寫。 GIT 很快,C 語言通過減少運作時的開銷來做到這一點。

6、在Git中,你如何還原已經 push 并公開的送出?

There can be two answers to this question and make sure that you include both because any of the below options can be used depending on the situation: 1 這個問題可以有兩個答案,你回答時也要保包含這兩個答案,因為根據具體情況可以使用以下選項:

  • 删除或修複新送出中的錯誤檔案,并将其推送到遠端存儲庫。這是修複錯誤的最自然方式。對檔案進行必要的修改後,将其送出到我将使用的遠端存儲庫
git commit -m "commit message"           
  • 建立一個新的送出,撤消在錯誤送出中所做的所有更改。可以使用指令:
git revert <name of bad commit>           

7、git pull 和 git fetch 有什麼差別?

git pull 指令從中央存儲庫中提取特定分支的新更改或送出,并更新本地存儲庫中的目标分支。

git fetch 也用于相同的目的,但它的工作方式略有不同。當你執行 git fetch 時,它會從所需的分支中提取所有新送出,并将其存儲在本地存儲庫中的新分支中。如果要在目标分支中反映這些更改,必須在 git fetch 之後執行 git merge 。隻有在對目标分支和擷取的分支進行合并後才會更新目标分支。為了友善起見,請記住以下等式:

git pull = git fetch + git merge           

8、git中的“staging area”或“index”是什麼?

For this answer try to explain the below diagram as you can see: 可以通過下圖進行解釋:

在完成送出之前,可以在稱為“staging area”或“index”的中間區域中對其進行格式化和審查。從圖中可以看出,每個更改首先在暫存區域中進行驗證,我将其稱為“stage fifile”,然後将更改送出到存儲庫。

Java面試題Git篇

9、什麼是 git stash?

首先應該解釋 git stash 的必要性。

通常情況下,當你一直在處理項目的某一部分時,如果你想要在某個時候切換分支去處理其他事情,事情會處于混亂的狀态。問題是,你不想把完成了一半的工作的送出,以便你以後就可以回到目前的工作。解決這個問題的答案是 git stash。

再解釋什麼是git stash。stash 會将你的工作目錄,即修改後的跟蹤檔案和暫存的更改儲存在一堆未完成的更改中,你可以随時重新應用這些更改。

10、什麼是git stash drop?

通過說明我們使用 git stash drop 的目的來回答這個問題。

git stash drop 指令用于删除隐藏的項目。預設情況下,它将删除最後添加的存儲項,如果提供參數的話,它還可以删除特定項。

下面舉個例子。

如果要從隐藏項目清單中删除特定的存儲項目,可以使用以下指令:

git stash list:它将顯示隐藏項目清單,如:stash@{0}: WIP on master: 049d078 added the index fifile stash@{1}: WIP on master: c264051Revert “added fifile_size” stash@{2}: WIP on master: 21d80a5 added number to log

如果要删除名為 stash@{0} 的項目,請使用指令 git stash drop stash@{0}。

11.、如何找到特定送出中已更改的檔案清單?

對于這個問題,不能僅僅是提供指令,還要解釋這個指令究竟做了些什麼。

要擷取特定送出中已更改的清單檔案,請使用以下指令:

git diffff-tree -r {hash}           

給定送出哈希,這将列出在該送出中更改或添加的所有檔案。 -r 标志使指令列出單個檔案,而不是僅将它們折疊到根目錄名稱中。

你還可以包括下面提到的内容,雖然它是可選的,但有助于給面試官留下深刻印象。

輸出還将包含一些額外資訊,可以通過包含兩個标志把它們輕松的屏蔽掉:

git diffff-tree –no-commit-id –name-only -r {hash}           

這裡 -no-commit-id 将禁止送出哈希值出現在輸出中,而 -name-only 隻會列印檔案名而不是它們的路徑。

12、git confifig 的功能是什麼?

首先說明為什麼我們需要 git config 。

git 使用你的使用者名将送出與身份相關聯。 git config 指令可用來更改你的 git 配置,包括你的使用者名。

下面用一個例子來解釋。

假設你要提供使用者名和電子郵件 ID 用來将送出與身份相關聯,以便你可以知道是誰進行了特定送出。為此,我将使用:

  • git confifig –global user.name "Your Name": 此指令将添加使用者名。
  • git confifig –global user.email "Your E-mail Address": 此指令将添加電子郵件ID。

13、送出對象包含什麼?

Commit 對象包含以下元件,你應該提到以下這三點:

  • 一組檔案,表示給定時間點的項目狀态;
  • 引用父送出對象;
  • SHAI 名稱,一個40個字元的字元串,送出對象的唯一辨別。

14、 如何在Git中建立存儲庫?

這可能是最常見的問題,答案很簡單。

要建立存儲庫,先為項目建立一個目錄(如果該目錄不存在),然後運作指令 git init。通過運作此指令,将在項目的目錄中建立 .git 目錄。

15、怎樣将 N 次送出壓縮成一次送出?

将N個送出壓縮到單個送出中有兩種方式:

  • 如果要從頭開始編寫新的送出消息,請使用以下指令:
git reset –soft HEAD~N &&           
git commit           
  • 如果你想在新的送出消息中串聯現有的送出消息,那麼需要提取這些消息并将它們傳給 git commit,可以這樣:
git reset –soft HEAD~N &&           
git commit –edit -m"$(git log –format=%B –reverse .HEAD@{N})"           

16、 什麼是 Git bisect?如何使用它來确定(回歸)錯誤的來源?

我建議你先給出一個Git bisect 的小定義。

Git bisect 用于查找使用二進制搜尋引入錯誤的送出。 Git bisect的指令是

git bisect <subcommand> <options>           

既然你已經提到過上面的指令,那就解釋一下這個指令會做什麼。

此指令用了二進制搜尋算法來查找項目曆史記錄中的哪個送出引入了錯誤。你可以通過告訴它已知包含該錯誤的“錯誤”送出以及在引入錯誤之前已知的“良好”送出來使用它。然後 git bisect 在這兩個端點之間選擇一個送出,并詢問你所選的送出是“好”還是“壞”。它繼續縮小範圍,直到找到引入更改的确切送出。

17、如果想要在送出之前運作代碼性檢查工具,并在測試失敗時阻止送出,該怎樣配置 Git 存儲庫?

我建議你先介紹一下完整性檢查。

完整性或冒煙測試用來确定繼續測試是否可行和合理。

下面解釋如何實作這一目标。

這可以通過與存儲庫的 pre-commit hook 相關的簡單腳本來完成。git 會在送出之前觸發 pre-commit hook。你可以在這個腳本中運作其他工具,例如 linters,并對送出到存儲庫中的更改執行完整性檢查。

最後舉個例子,你可以參考下面的腳本:

#!/bin/sh
files=$(git diff –cached –name-only –diff-filter=ACM | grep ‘.go$’)
if [ -z files ]; then
 exit 0
fi
unfmtd=$(gofmt -l $files)
if [ -z unfmtd ]; then
 exit 0
fi
echo “Some .go files are not fmt’d”
exit 1
           

這段腳本檢查是否需要通過标準 Go 源代碼格式化工具 gofmt 傳遞所有即将送出的 .go 檔案。如果腳步以非 0 狀态退出,腳本會有效地阻止送出操作。

18.、描述一下你所使用的分支政策?

這個問題被要求用Git來測試你的分支經驗,告訴他們你在以前的工作中如何使用分支以及它的用途是什麼,你可以參考以下提到的要點:

功能分支(Feature branching)

要素分支模型将特定要素的所有更改保留在分支内。當通過自動化測試對功能進行全面測試和驗證時,該分支将合并到主伺服器中。

任務分支(Task branching)

在此模型中,每個任務都在其自己的分支上實作,任務鍵包含在分支名稱中。很容易看出哪個代碼實作了哪個任務,隻需在分支名稱中查找任務鍵。

釋出分支(Release branching)

一旦開發分支獲得了足夠的釋出功能,你就可以克隆該分支來形成釋出分支。建立該分支将會啟動下一個釋出周期,是以在此之後不能再添加任何新功能,隻有錯誤修複,文檔生成和其他面向釋出的任務應該包含在此分支中。一旦準備好釋出,該版本将合并到主伺服器并标記版本号。此外,它還應該再将自釋出以來已經取得的進展合并回開發分支。

最後告訴他們分支政策因團隊而異,是以我知道基本的分支操作,如删除、合并、檢查分支等。

19、如果分支是否已合并為master,你可以通過什麼手段知道?

答案很直接。

要知道某個分支是否已合并為master,你可以使用以下指令:

  • git branch –merged 它列出了已合并到目前分支的分支。
  • git branch –no-merged 它列出了尚未合并的分支。

20、 什麼是SubGit?

SubGit 是将 SVN 到 Git遷移的工具。它建立了一個可寫的本地或遠端 Subversion 存儲庫的 Git 鏡像,并且隻要你願意,可以随意使用 Subversion 和 Git。

這樣做有很多優點,比如你可以從 Subversion 快速一次性導入到 Git 或者在 Atlassian BitbucketServer 中使用SubGit。我們可以用 SubGit 建立現有 Subversion 存儲庫的雙向 Git-SVN 鏡像。你可以在友善時 push 到 Git 或送出 Subversion。同步由 SubGit 完成。

21、列舉工作中常用的幾個git指令?

新增檔案的指令:git add fifile或者git add . 送出檔案的指令:git commit –m或者git commit –a 檢視工作區狀況:git status –s 拉取合并遠端分支的操作:git fetch/git merge或者git pull 檢視送出記錄指令:git reflflog

22、如果本次送出誤操作,如何撤銷?

如果想撤銷送出到索引區的檔案,可以通過git reset HEAD fifile;如果想撤銷送出到本地倉庫的檔案,可以通過git reset –soft HEAD^n恢複目前分支的版本庫至上一次送出的狀态,索引區和工作空間不變更;可以通過git reset –mixed HEAD^n恢複目前分支的版本庫和索引區至上一次送出的

23、你使用過git stash指令嗎?你一般什麼情況下會使用它?

指令git stash是把工作區修改的内容存儲在棧區。 以下幾種情況會使用到它:

  • 解決沖突檔案時,會先執行git stash,然後解決沖突;
  • 遇到緊急開發任務但目前任務不能送出時,會先執行git stash,然後進行緊急任務的開發,然後通過git stash pop取出棧區的内容繼續開發;
  • 切換分支時,目前工作空間内容不能送出時,會先執行git stash再進行分支切換;

24、如何檢視分支送出的曆史記錄?檢視某個檔案的曆史記錄呢?

檢視分支的送出曆史記錄:

  • 指令git log –number:表示檢視目前分支前number個詳細的送出曆史記錄;
  • 指令git log –number –pretty=oneline:在上個指令的基礎上進行簡化,隻顯示sha-1碼和送出資訊;
  • 指令git reflflog –number: 表示檢視所有分支前number個簡化的送出曆史記錄;
  • 指令git reflflog –number –pretty=oneline:顯示簡化的資訊曆史資訊;

如果要檢視某檔案的送出曆史記錄,直接在上面指令後面加上檔案名即可。

注意:如果沒有number則顯示全部送出次數。

25、使用過git merge和git rebase嗎?它們之間有什麼差別?

簡單的說,git merge和git rebase都是合并分支的指令。 git merge branch會把branch分支的差異内容pull到本地,然後與本地分支的内容一并形成一個committer對象送出到主分支上,合并後的分支與主分支一緻; git rebase branch會把branch分支優先合并到主分支,然後把本地分支的commit放到主分支後面,合并後的分支就好像從合并後主分支又拉了一個分支一樣,本地分支本身不會保留送出曆史。

26、使用過git cherry-pick,有什麼作用?

指令git cherry-pick可以把branch A的commit複制到branch B上。 在branch B上進行指令操作:

  • 複制單個送出:git cherry-pick commitId
  • 複制多個送出:git cherry-pick commitId1…commitId3

注意:複制多個送出的指令不包含commitId1

繼續閱讀