在今年的 Stack Overflow 開發者調查報告中,超過 70% 的開發者使用 Git,使其成為世界上使用人數最多的版本控制系統。Git 通常用於開源和商業軟體開發,對個人、團隊和企業都頗有益處。
Q1: 什麼是 Git 復刻(fork)?復刻(fork)、分支(branch)和克隆(clone)之間有什麼區別?
主題:Git 難度:⭐⭐
- 復刻(fork) 是對儲存倉庫(repository)進行的遠端的、伺服器端的拷貝,從源頭上就有所區別。復刻實際上不是 Git 的範疇。它更像是個政治/社會概念。
- 克隆(clone) 不是復刻,克隆是個對某個遠端倉庫的本地拷貝。克隆時,實際上是拷貝整個源儲存倉庫,包括所有歷史記錄和分支。
- 分支(branch) 是一種機制,用於處理單一儲存倉庫中的變更,並最終目的是用於與其他部分程式碼合併。
?來源: stackoverflow.com
Q2: “拉取請求(pull request)”和“分支(branch)”之間有什麼區別?
主題:Git 難度:⭐⭐
- 分支(branch) 是程式碼的一個獨立版本。
- 拉取請求(pull request) 是當有人用倉庫,建立了自己的分支,做了些修改併合併到該分支(把自己修改應用到別人的程式碼倉庫)。
?來源: stackoverflow.com
Q3: “git pull”和“git fetch”之間有什麼區別?
主題:Git 難度:⭐⭐
簡單來說,git pull
是 git fetch
+ git merge
。
- 當你使用
pull
,Git 會試著自動為你完成工作。它是上下文(工作環境)敏感的,所以 Git 會把所有拉取的提交合併到你當前處理的分支中。pull
則是 自動合併提交而沒有讓你複查的過程。如果你沒有細心管理你的分支,你可能會頻繁遇到衝突。 - 當你
fetch
,Git 會收集目標分支中的所有不存在的提交,並將這些提交儲存到本地倉庫中。但Git 不會把這些提交合併到當前分支中。這種處理邏輯在當你需要保持倉庫更新,在更新檔案時又希望處理可能中斷的事情時,這將非常實用。而將提交合併到主分支中,則該使用merge
。
?來源: stackoverflow.com
Q4: 如在 Git 恢復先前的提交?
主題:Git 難度:⭐⭐⭐
假設你的情形是這樣,其中 C 是你的 HEAD,(F) 是你檔案的狀態。
1 2 3 4 |
(F) A-B-C ↑ master |
- 要修改提交中的更改:
1 |
git reset --hard HEAD~1 |
現在 B 是 HEAD,因為你使用了 --hard
,所以你的檔案將重置到提交 B 時的狀態。
- 要撤銷提交但保留更改:
1 |
git reset HEAD~1 |
現在我們告訴 Git 將 HEAD 指標移回(後移)一個提交(B),並保留檔案原樣,然後你可以 git status
來顯示你已經檢入 C 的更改。
- 撤銷提交但保留檔案和索引:
1 |
git reset --soft HEAD~1 |
執行此操作後,git status
,你講看到索引中的檔案跟以前一致。
?來源: stackoverflow.com
Q5: 什麼是“git cherry-pick”?
主題:Git 難度:⭐⭐⭐
命令 git cherry-pick
通常用於把特定提交從儲存倉庫的一個分支引入到其他分支中。常見的用途是從維護的分支到開發分支進行向前或回滾提交。
這與其他操作(例如:合併(merge)、變基(rebase))形成鮮明對比,後者通常是把許多提交應用到其他分支中。
小結:
1 |
git cherry-pick <commit-hash> |
?來源: stackoverflow.com
Q6: 解釋 Forking 工作流程的優點
主題:Git 難度:⭐⭐⭐
Forking 工作流程 與其他流行的 Git 工作流程有著根本的區別。它不是用單個服務端倉庫充當“中央”程式碼庫,而是為每個開發者提供自己的服務端倉庫。Forking 工作流程最常用於公共開源專案中。
Forking 工作流程的主要優點是可以彙集提交貢獻,又無需每個開發者提交到一箇中央倉庫中,從而實現乾淨的專案歷史記錄。開發者可以推送(push)程式碼到自己的服務端倉庫,而只有專案維護人員才能直接推送(push)程式碼到官方倉庫中。
當開發者準備釋出本地提交時,他們的提交會推送到自己的公共倉庫中,而不是官方倉庫。然後他們向主倉庫提交請求拉取(pull request),這會告知專案維護人員有可以整合的更新。
?來源: atlassian.com
Q7: 告訴我 Git 中 HEAD、工作樹和索引之間的區別?
主題:Git 難度:⭐⭐⭐
- 該工作樹/工作目錄/工作空間是你看到和編輯的(源)檔案的目錄樹。
- 該索引/中轉區(staging area)是個在
/.git/index
,單一的、龐大的二進位制檔案,該檔案列出了當前分支中所有檔案的 SHA1 檢驗和、時間戳和檔名,它不是個帶有檔案副本的目錄。 - HEAD是當前檢出分支的最後一次提交的引用/指標。
?來源: stackoverflow.com
Q8: 你能解釋下 Gitflow 工作流程嗎?
主題:Git 難度:⭐⭐⭐
Gitflow 工作流程使用兩個並行的、長期執行的分支來記錄專案的歷史記錄,分別是 master
和 develop
分支。
- Master,隨時準備釋出線上版本的分支,其所有內容都是經過全面測試和核準的(生產就緒)。
- Hotfix,維護(maintenance)或修復(hotfix)分支是用於給快速給生產版本修復打補丁的。修復(hotfix)分支很像釋出(release)分支和功能(feature)分支,除非它們是基於
master
而不是develop
分支。
- Hotfix,維護(maintenance)或修復(hotfix)分支是用於給快速給生產版本修復打補丁的。修復(hotfix)分支很像釋出(release)分支和功能(feature)分支,除非它們是基於
- Develop,是合併所有功能(feature)分支,並執行所有測試的分支。只有當所有內容都經過徹底檢查和修復後,才能合併到
master
分支。- Feature,每個功能都應留在自己的分支中開發,可以推送到
develop
分支作為功能(feature)分支的父分支。
- Feature,每個功能都應留在自己的分支中開發,可以推送到
?來源: atlassian.com
Q9: 什麼時候應使用 “git stash”?
主題:Git 難度:⭐⭐⭐
git stash
命令把你未提交的修改(已暫存(staged)和未暫存的(unstaged))儲存以供後續使用,以後就可以從工作副本中進行還原。
回顧:
1 2 3 4 5 6 7 8 9 10 11 12 |
$ git status On branch master Changes to be committed: new file: style.css Changes not staged for commit: modified: index.html $ git stash Saved working directory and index state WIP on master: 5002d47 our new homepage HEAD is now at 5002d47 our new homepage $ git status On branch master nothing to commit, working tree clean |
我們可以使用暫存(stash)的一個地方是,如果我們發現在上次提交中忘記了某些內容,並且已經開始在同一分支中處理下一個提交了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# Assume the latest commit was already done # start working on the next patch, and discovered I was missing something # stash away the current mess I made $ git stash save # some changes in the working dir # and now add them to the last commit: $ git add -u $ git commit --ammend # back to work! $ git stash pop |
?來源: atlassian.com
Q10: 如何從 git 中刪除檔案,而不將其從檔案系統中刪除?
主題:Git 難度:⭐⭐⭐⭐
如果你在 git add
過程中誤操作,你最終會新增不想提交的檔案。但是,git rm
則會把你的檔案從你暫存區(索引)和檔案系統(工作樹)中刪除,這可能不是你想要的。
換成 git reset
操作:
1 2 |
git reset filename # or echo filename >> .gitingore # add it to .gitignore to avoid re-adding it |
上面意思是,git reset <paths>
是 git add <paths>
的逆操作。
?來源: codementor.io
Q11: 是麼時候使用“git rebase”代替“git merge”?
主題:Git 難度:⭐⭐⭐⭐⭐
這兩個命令都是把修改從一個分支整合到另一個分支上,它們只是以非常不同的方式進行。
考慮一下場景,在合併和變基前:
1 2 3 4 |
A <- B <- C [master] ^ \ D <- E [branch] |
在 git merge master
之後:
1 2 3 4 |
A <- B <- C ^ ^ \ \ D <- E <- F |
在 git rebase master
之後:
1 |
A <- B <- C <- D <- E |
使用變基時,意味著使用另一個分支作為整合修改的新基礎。
何時使用:
- 如果你對修改不夠果斷,請使用合併操作。
- 根據你希望的歷史記錄的樣子,而選擇使用變基或合併操作。
更多需要考慮的因素:
- 分支是否與團隊外部的開發人員共享修改(如開源、公開專案)?如果是這樣,請不要使用變基操作。變基會破壞分支,除非他們使用
git pull --rebase
,否則這些開發人員將會得到損壞的或不一致的倉庫。 - 你的開發團隊技術是否足夠嫻熟?變基是一種破壞性操作。這意味著,如果你沒有正確使用它,你可能會丟失提交,並且/或者會破壞其他開發者倉庫的一致性。
- 分支本身是否代表有用的資訊?一些團隊使用功能分支(branch-per-feature)模式,每個分支代表一個功能(或錯誤修復,或子功能等)。在此模式中,分支有助於識別相關提交的集合。在每個開發人員分支(branch-per-developer)模式中,分支本身不會傳達任何其他資訊(提交資訊已有作者)。則在這種模式下,變基不會有任何破壞。
- 是否無論如何都要還原合併?恢復(如在撤銷中)變基,是相當困難的,並且/或者在變基中存在衝突時,是不可能完成的。如果你考慮到日後可能需要恢復,請使用合併操作。
?來源: stackoverflow.com
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!
任選一種支付方式