1. 程式人生 > 其它 >原始碼配置管理(Git)

原始碼配置管理(Git)

版本控制

CVS(英語:Concurrent Versions System,或Concurrent Versioning System)代表協作版本系統或者併發版本系統,是一種版本控制系統,方便軟體的開發和使用者協同工作。

很多開源或者自由軟體專案都使用CVS作為其程式設計師之間的中心點,以便能夠綜合各程式設計師的改進和更改。這些專案包括:GnomeKDEGIMPWine等。CVS的使用獲GNU通用公共許可證授權。

這是一個將一組檔案放在層次目錄樹中以保持同步的系統。人們可以從CVS伺服器上更新他們的本地層次樹副本,並將修改的結果或新檔案發回;或者刪除舊檔案。

CVS基於客戶端/伺服器結構

的行為使得其可容納多使用者,構成網路也很方便。這一特性使得CVS成為位於不同地點的人同時處理資料檔案(特別是程式的原始碼)時的首選(現已被GitSVN等逐漸替代)。 - wikipedia

軟體配置管理(Software Configuration Management,簡稱:SCM),又稱軟體形態管理、或軟體建構管理,簡稱軟體形管。界定軟體的組成專案,對每個專案變更進行管控(版本控制),並維護不同專案之間的版本關係,以使軟體在開發過程中任一時間的內容都可以被追溯,包括某幾個具有重要意義的數個組合,例如某一次交付給客戶的軟體內容。

SCM的簡稱已經擴充套件為“原始碼配置管理”(source configuration management)以及“軟體修改及配置管理” (software change and configuration management)。不過,“配置”一詞一般還是會指

系統管理員才能進行的變更。

SCM的目標一般包括以下幾項:

  • 配置識別:識別配置、配置專案基準
  • 配置控管:匯入變更控管流程。該流程通常由變更控制委員會來執行,其主要的職責是核准或拒絕有悖任何基準的所有變更請求。
  • 配置狀態報告:記錄和呈報與開發過程狀態相關的所有必要資訊。
  • 配置稽核:確保這些配置包含所有預期內容,且備有完整的規定檔案(包括要求、結構規範和使用者手冊)。
  • 建構管理:管理用於建構的流程和工具。
  • 流程管理:確保遵循企業組織的開發流程。
  • 環境管理:管理承載系統的軟硬體。
  • 團隊合作:促進流程中團隊彼此間的互動。
  • 缺陷追蹤:確保可溯及每個缺陷的源頭。 - wikipedia

Git vs SVN

See https://github.com/xirong/my-git/blob/master/why-git.md

SVN

集中式,無本地分支

Git

分散式:本地倉庫&遠端倉庫

面向物件:內容定址系統。.git目錄下的資料夾objects儲存了git庫中的物件。

.git目錄

➜  .git git:(master) ls -F1
COMMIT_EDITMSG
HEAD
ORIG_HEAD
config
description
hooks/
index
info/
logs/
objects/
packed-refs
refs/

HEAD是一個特殊的指標,它是指標的指標。它用來標記當前的提交。當你使用git checkout branch, HEAD指標就會發生移動。 當你新建一個分支的時候其實僅僅是改變了HEAD的指向,這也是git分支比較輕量的原因。

hooks是鉤子。用來在git操作前後進行一些操作。 比如下面講的husky外掛就是基於這個原理實現的。

index是本地的暫存區

objects儲存了git庫中的物件。

# 檢視物件型別
git cat-file -t hash
git cat-file -p 001ab1dbd031b06b88acf247c2734a6ce5f2c2f1

git就是根據object建立一種樹形結構。將檔案和通過hash的方式關聯起來。

refs其實是分支的引用。

暫存區 vs 工作區 vs 遠端倉庫

sequenceDiagram participant ut as Untracked participant um as Unmodified participant m as Modified participant s as Staged ut ->> s: Add the file um ->> m: Edit the file m ->> s: Stage the file um ->> ut: Remove the file s ->> um: Commit

Git安裝

git-scm

Git外掛

git-extras

git-lfs: 大檔案支援

for nodejs: husky commitzen coventional-changelog

for vscode: git blame or git lens

for shell: git git-flow

一個很有意思的學習 Git 的小遊戲 http://pcottle.github.io/learnGitBranching/

各種語言、各種編輯器的.gitignore檔案模板 .gitignore template

Git Workflow

See https://github.com/xirong/my-git/blob/master/git-workflow-tutorial.md

集中式工作流

用和Subversion相同的方式。

功能分支工作流

功能分支工作流以集中式工作流為基礎,不同的是為各個新功能分配一個專門的分支來開發。這樣可以在把新功能整合到正式專案前,用Pull Requests的方式討論變更。

Gitflow工作流

git flow

hotfix:工作分支,用於修復線上bug

feature:工作分支,用於開發新的功能

develop:合併分支,用於合併 hotfixfeaturedevelop彙總了所有的功分支程式碼。當 develop程式碼達到穩定狀態(測試完成),將其合併到 release 分支。

所有的分支只有 masterdevelop 是長期分支。

release:合併分支,用於釋出某一個版本,通常採用 semverrelease分支通常不做任何程式碼修改,僅僅修改版本號和構建資訊。作為釋出生產最後一步,可以進行小範圍的程式碼修改。

master:這裡應該是隨時可以釋出的程式碼,不可對其進行任何提交,只可以從 hotfix 或者 release 合併。

如果合併到develop中的一個分支沒有通過測試,無法釋出,其他分支需要釋出怎麼辦?

這就需要checkout develop,然後revert指定feature分支合併的commit id。這也就是為什麼 git flow 合併分支需要非快速合併的原因(--no-ff)

See https://nvie.com/posts/a-successful-git-branching-model/

anti git-flow

merge-commit hell

$ git merge --no-ff myfeature

The --no-ff flag causes the merge to always create a new commit object, even if the merge could be performed with a fast-forward.

master/develop split

When the source code in the develop branch reaches a stable point and is ready to be released, all of the changes should be merged back into master somehow and then tagged with a release number. How this is done in detail will be discussed further on.

Therefore, each time when changes are merged back into master, this is a new production release by definition. We tend to be very strict at this, so that theoretically, we could use a Git hook script to automatically build and roll-out our software to our production servers everytime there was a commit on master.

complex
  • Reverting somebody else’s changes because of conflicts happening during a merge and the inability to find the correct version in history
  • Confusing to which branch should a change be actually pushed (this happens so often it might be called a “standard” mistake)
  • Starting a support branch from the wrong initial branch, or finishing a support branch by merging to the wrong final branch
  • Forgetting to tag a release (cause there was a commit on master, right?), and so then accidentally changing the release in place, instead of creating a new one
  • Not building the actual release from the commit that is later tagged with the (supposed) release number
Anti-gitflow
  • There is only one eternal(長期) branch – you can call it master, develop, current, next – whatever. I personally like “master”, and that’s the name I’ll use in the rest of the description, as it’s convention by now in the Git world and immediately conveys its purpose.
  • All other branches (feature, release, hotfix, and whatever else you need) are temporary and only used as a convenience to share code with other developers and as a backup measure. They are always removed once the changes present on them land on master.
  • Features are integrated onto the master branch primarily in a way which keeps the history linear. You have a lot of leeway in how you want to enforce this. You can make it simply a convention that developers are encouraged, but not forced, to follow. On the other side of the spectrum, if you use something like Gerrit to manage your Git repositories (which I recommend, even if you don’t practice code reviews – the permission system is fantastic, and if you ever decide you want code reviews, it’ll be very easy to start doing them), you can set up permissions in such a way that actually forbids pushing merge commits to master, and that way ensure linear history.
  • Releases are done similarly to in GitFlow. You create a new branch for the release, branching off at the point in master that you decide has all the necessary features. From then on new work, aimed for the next release, is pushed to master as always, and any necessary changes are pushed to the release branch (in my opinion, it’s an anti-pattern and a huge red flag if your release requires separate commits to work, but that’s a topic for another article – for simplicity, let’s assume you can’t or don’t want to change that). Finally, once the release is ready, you tag the top of the release branch. Then, because there is one eternal branch, there is only one way to get your release to be versioned permanently – and that is to merge the release branch into master and push that changed master. After that, all the changes that were made during the release are now part of master, and the release branch is deleted.
  • Hotfixes are very similar to releases, except you don’t branch from an arbitrary commit on master, but from the release tag that you want to make the fix in. Again, work on master continues as always, and the necessary fixes are pushed to the hotfix branch. Once the fix is ready, the procedure is exactly the same as for a release – tag the top of the branch creating a new release, merge it into master, then delete the hotfix branch.

Forking工作流

Forking工作流是分散式工作流,充分利用了Git在分支和克隆上的優勢。可以安全可靠地管理大團隊的開發者(developer),並能接受不信任貢獻者(contributor)的提交。

Pull Requests

Pull requestsBitbucket提供的讓開發者更方便地進行協作的功能,提供了友好的Web介面可以在提議的修改合併到正式專案之前對修改進行討論。

Commit Message

feat: 增加一個新特性
fix(module-a): 修復一個bug #89123
doc: 增加文件
chore: 增加註釋

Cheatsheets

  • Visual Git Cheat Sheet 通過 Git 的幾個工作區 Stash、Workspace、Index、Local Repository、Upstream Repository 來彙總日常使用的 Git 命令,備忘推薦。

TODO

Art is long, and life is short.