天天看點

2019 DevOps 必備面試題——代碼版本控制篇

原文位址: https://medium.com/edureka/devops-interview-questions-e91a4e6ecbf3

原文作者:Saurabh Kulshrestha

翻譯君:CODING 戴維奧普斯

Q1:什麼是版本控制?

這可能是你在面試中遇到的最簡單的問題。我的建議是首先給出版本控制的定義:它是一個記錄檔案變化的系統,以便你以後可以調用特定版本的檔案。版本控制系統由一個中央共享存儲庫組成,隊友可以在其中送出檔案的更改,接下來你可以提到版本控制的用途。版本控制允許你:

  • 将檔案還原為以前的狀态。
  • 将整個項目還原為以前的狀态。
  • 比較一段時間内的變化。
  • 檢視最後一次修改可能導緻問題的内容。
  • 何時引入了問題。

Q2:使用版本控制有什麼好處?

版本控制的優點:

  1. 使用版本控制系統(VCS),所有團隊成員都可以随時在任何檔案上自由工作。VCS 允許你将所有更改合并到一個通用版本中。
  2. 所有過去的版本和變更都整齊地打包在 VCS 中。當你需要它時,你可以随時請求任何版本,你将獲得完整項目的快照。
  3. 每次儲存項目的新版本時,VCS 都要求你提供更改内容的簡短說明。此外,你還可以檢視檔案内容的确切更改内容。這可以讓你知道誰在項目中做了哪些更改。
  4. 像 Git 這樣的分布式 VCS 允許所有團隊成員擁有項目的完整曆史記錄,是以如果中央伺服器出現故障,你可以使用任何團隊成員的本地 Git 存儲庫來恢複代碼庫。

Q3:描述你使用的分支政策

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

  • 特性分支

    特性分支模型保留分支内特定功能的所有更改。當通過新增特性的全面測試和驗證時,該分支會被合并到 master 分支中。

  • 任務分支

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

  • 釋出分支

    一旦開發分支為釋出獲得了足夠的特性時,你就可以克隆該分支以形成釋出分支。建立此分支将啟動下一個釋出周期,是以在這之後不能添加任何新功能,隻有錯誤修複、文檔補齊和其它面向釋出的任務能夠包含在此分支中。一旦準備好釋出,該版本将合并到 master 中并标記版本号。此外,盡管自釋出以來開發分支可能已經有新的代碼更新,但它依然應該被合并回開發分支。

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

Q4:你熟悉哪種 VCS 工具?

你可以提到你曾經使用的 VCS 工具:“我使用過 Git,它對比 SVN 等其他 VCS 工具的一個主要優勢在于,它是一個分布式版本控制系統。” 

分布式 VCS 工具不一定依靠中央伺服器來存儲項目檔案的所有版本。相反,每個開發人員都“克隆”存儲庫的副本,并在自己的硬碟上擁有項目的完整曆史記錄。

Q5:什麼是 Git?

我建議你通過解釋 Git 的體系結構來解答這個問題,如下圖所示。你可以參考下面給出的解釋:

  • Git 是一個分布式版本控制系統(DVCS),它可以跟蹤檔案的更改,并允許你恢複任何特定的更改。
  • 與 SVN 等其它版本控制系統相比,它的分布式架構具有許多優勢,一個主要優點是它不依賴于中央伺服器來存儲項目檔案的所有版本。相反,每個開發人員“克隆”我在下圖中使用“本地存儲庫”顯示的存儲庫副本,并在其硬碟驅動器上具有項目的完整曆史記錄,以便在出現伺服器中斷時,能從你的某位隊友的本地 Git 存儲庫中恢複所需的全部内容。
  • 還有一個中央雲存儲庫,開發人員可以送出更改并與其他團隊成員共享。如圖所示,所有協作者都送出更改至“遠端存儲庫”。
2019 DevOps 必備面試題——代碼版本控制篇

Q6:解釋一些基本的 Git 指令?

以下是一些基本的 Git 指令:

2019 DevOps 必備面試題——代碼版本控制篇

Q7:在 Git 中,如何還原已經被推送并公開的送出?

此問題可以有兩個答案,根據具體情況可以使用以下任意選項:

  • 在新送出中删除或修複錯誤檔案,并将其推送到遠端存儲庫。這是修複錯誤最自然的方式。對檔案進行必要的更改後,将其送出到遠端存儲庫,我将使用:

    git commit -m“commit message”

  • 建立一個新的送出,撤消在錯誤送出中所做的所有更改,使用指令:

    git revert

Q8:如何将 N 次送出壓縮成一次送出?

将 N 個送出壓縮到單個送出中有兩種選擇。在你的答案中包括以下兩個選項:

  • 如果要從頭開始編寫新的送出消息,請使用以下指令:

    git reset -soft HEAD~N && 

git commit

  • 如果你想通過串接現有送出資訊來編輯新的送出資訊,那麼你需要提取出這些消息并傳遞給 Git commit 。我會使用:

git commit -edit -m “$(git log -format =%B -reverse .HEAD @ {N})”

Q9:什麼是 Git bisect?如何用它來确定 bug 的來源?

我建議你先給出一個 Git bisect 的小定義——Git bisect 用于通過二進制搜尋算法來查找引入 bug 的送出。Git bisect 的指令是:

git bisect <子指令>

接下來需要解釋一下這個指令可以做什麼,這個指令使用二進制搜尋算法來查找項目曆史中哪個送出引入了一個 bug。首先你需要告訴它一個已知的包含了該 bug 的送出和在一個已知的引入 bug 之前的送出。然後 Git bisect 在這兩個時間點之間選擇一個送出,并詢問你所選的送出是“好”還是“壞”,之後它繼續縮小範圍,直到找到引入 bug 的确切送出。

Q10:什麼是 Git rebase?它如何在合并之前解決特性分支中的沖突?

你應該首先說 Git rebase 是一個指令,它将另一個分支合并到目前你正在工作的分支中,并将所有位于另一分支之前的本地送出,移到該目前工作分支曆史記錄頂部。

接下來你需要通過一個示例定義 Git rebase 時間窗,以顯示如何在合并之前使用它來解決特性分支中的沖突。如果從 master 建立了一個特性分支,那麼 master 已經收到了新的送出,Git rebase 可用于将特性分支移動到 master 分支的頂部。

該指令有效地在 master 的頂部重放特性分支中所做的更改,并允許在該過程中解決沖突。完成後,特性分支會相對容易地合并到 master 中,有時會被作為簡單的快進操作。

Q11:如何配置 Git 存儲庫,以在送出之前運作代碼健康性檢查工具,并在測試失敗時阻止送出?

我建議你先簡要介紹一下合理性檢查。合理性或冒煙測試可以用來确定是否進行後續測試的合理性和必要性。

接下來解釋如何實作這一點,這可以通過與存儲庫的預送出鈎子相關的簡單腳本來完成。即使在你需要輸入送出消息之前,也會在送出之前觸發預送出挂鈎。在此腳本中,可以運作其它工具,例如 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 檔案是否通過标準 Go 源碼格式化工具 —— gofmt 的檢驗。當檢查未通過時,通過以非零狀态退出,腳本能有效地阻止該送出應用于存儲庫。

Q12:如何找到特定送出中已更改的檔案清單?

對于這個問題,不應該僅僅隻解釋這個指令是什麼,而應該解釋這個指令究竟會做什麼。是以你可以這麼說,為了獲得在特定送出中更改的檔案清單使用指令:

git diff-tree -r {hash} 

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

你的回答也可以包含以下内容,雖然它是完全可選的,但有助于給面試官留下深刻的印象:

輸出還将包含一些額外資訊,可以通過以下兩個标志輕松去掉:

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

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

Q13:每次存儲庫接收到新推送的送出時,如何設定某些特定腳本運作?

每次存儲庫接收到開發者 push 的新送出時,有三種方法可以配置腳本運作,需要根據觸發腳本的時間來定義 pre-receive、update、或者 post-receive 腳本。

  • 當有新送出被 push 到目标存儲庫時,将調用目标存儲庫中的 pre-receive 鈎子腳本。綁定到此挂鈎的任何腳本都将在更新任何引用之前執行。這是一個很有用的鈎子,可以用于運作有助于實施開發政策的腳本。
  • update 鈎子以類似 pre-receive 鈎子的方式工作,并且在實際進行任何更新之前也會觸發。但是對于已推送到目标存儲庫的每個送出,都會調用一次 update 鈎子。
  • 最後,在将更新接受到目标存儲庫後,将調用存儲庫中的 post-receive 鈎子。這是配置簡單部署腳本、調用持續內建系統、向存儲庫維護人員發送通知電子郵件等事務的理想場所。

鈎子是每個 Git 存儲庫的本地存儲,并且沒有版本化。腳本可以在“.git”目錄内的 hooks 目錄中建立,也可以在别處建立,并且可以在目錄中放置這些腳本的連結。

Q14:如何知道分支是否已經合并入主分支?

我建議你提到以下指令:

git branch -merged 列出已合并到目前分支的分支。

git branch -no-merged 列出了尚未合并的分支。