github flow場景
第一步:根據需求,從master拉出新分支,不區分功能分支或補丁分支。
第二步:新分支開發完成后,或者需要討論的時候,就向master發起一個pull request(簡稱PR)。
第三步:Pull Request既是一個通知,讓別人注意到你的請求,又是一種對話機制,大家一起評審和討論你的代碼。對話過程中,你還可以不斷提交代碼。
第四步:你的Pull Request被接受,合並進master,重新部署后,原來你拉出來的那個分支就被刪除。(先部署再合並也可。)
這個場景滿足絕大多數的中小項目開發需求。
多主干場景
場景描述如下:
- 當前倉庫是個通用組件,需要同時維護多個版本,如 1.x,2.x。
- 倉庫代碼針對多個場景的輸出,對應的源碼有差別,但需要同時維護。
- 倉庫代碼發布線上后,發布線上的代碼不想立刻合並到 master,待確認線上穩定后再合並。
多主干項目v1版
a人開發分支為daily/1.0.0。
然后從daily/1.0.0切出功能分支feature/describe
,開發測試完畢后合並到daily/1.0.0,並刪除feature/describe
分支。
發布分支從publish/1.0.0開始遞增。
publish分支發布后,會合並到開發分支daily/1.0.0
,但不會把代碼合到master。
b人開發分支也為daily/1.0.0,發布前需合並一下publish/1.x.x
的最新版本。
多主干項目v2版
a人開發分支為daily/2.0.0
.
然后從daily/2.0.0
切出功能分支feature/describe
,開發測試完畢后合並到daily/1.0.0,並刪除feature/describe
分支。
發布分支從publish/2.0.0開始遞增。
publish分支發布后,會合並到開發分支daily/2.0.0
,但不會把代碼合到master。
b人開發分支也為daily/2.0.0,發布前需合並一下publish/2.x.x
的最新版本。
注意
以上功能只是一個思路,非git自帶,需要自定義開發。
這種多主干場景也可以用fork倉庫方式解決。
也就是Github fork其他項目的分支與主干保持同步
。
Github fork其他項目的分支與主干保持同步
Fork一個Repo
Fork是一個復制的操作,當你Fork一個項目之后,你就有了在原項目的基礎之上進行修改和擴展的權限。
通常情況下,Fork操作用於參與別人的項目(成為項目中的一員),或者以別人的項目為基礎來開發自己的項目。
當你使用一個開源項目的時候,如果項目中存在bug,除了可以將bug報告項目開發人員。你也可以通過Fork原項目,並參與進來。
- 首先,Fork原項目,並將項目代碼更新到你的本地;
- 其次,修復項目中的bug,並確認問題已修復;
- 最后,如果一切測試都沒有問題,你就可以提交一個pull request給項目所有人,如果項目所有者認可你的代碼,他就會將你的修改更新到原項目中;
在Github中,Fork一個開源項目主要有兩步:
查找到你想要Fork的項目;
點擊項目介紹頁面右上角的Fork;
保持同步
當你Fork一個項目之后,你的項目與原項目之間就不存在聯系了,當原項目有更新的時候,你自己Fork的項目也不會同步保持更新。為了保持與原項目的一致,你需要使用到Git的命令行。
第一步 安裝git客戶端
如果你沒有安裝git的客戶端,你需要先去下載git的客戶端並安裝,windows系統git下載安裝地址:http://git-scm.com/download/
第二步 clone你fork的項目
fork一個項目使用git命令行clone項目:git clone git@github:[yourname]/Spoon-knife
第三步 添加新的遠程倉庫地址
當你clone完一個項目,可以使用git remote -v
來查看你fork的遠程倉庫的地址;默認的clone操作完成后,遠端倉庫的地址別名為:origin,為了需要與原項目保持更新,你還需要將原項目地址給添加進來,使用命令:git remote add upstream git@github.com:octocat/Spoon-Knife.git
可以添加遠端倉庫地址,其中upstream
為新的遠端倉庫的別名。
第四步 同步更新
假設你已經完成了前三步,當原項目有更新的時候,怎么將更新檢入到本地吶,主要是以下幾個步驟:
打開git命令行工具;
進入項目本地路徑;
執行git fetch upstream
命令,檢出upstream
分支以及各自的更新。
切換到你的本地分支主干:git checkout master
。
合並upsteram/master分支和master分支,將原項目中的更改更新到本地分支,這樣就能使你的本地的fork分支與原項目保持同步,命令為git merge upstream/master
。
或者使用命令git cherry-pick
挑幾個commit來合並。
執行git push將本地分支的修改推送到遠端fork的項目。
參考:https://www.cnblogs.com/kakag/p/4287536.html
子模塊場景
當前git項目依賴另一個git項目。
你想將兩個項目單獨處理但是又需要在其中一個中使用另外一個。
子模塊變更
在子模塊中的git操作就和獨立的git項目操作一樣。
進入到子模塊目錄,提交變更。
$ git add .
$ git commit -m "commit"
$ git push origin HEAD:master
提交完子模塊的變更,還要回到父模塊的目錄,提交下子模塊的變動。
cd ..
git status
git commit -m 'update submodule'
git push origin
子模塊更新
在父模塊的目錄下更新子模塊
git submodule update --recursive
在子模塊的目錄下,就是正常git操作
git pull
clone包含子模塊的父模塊倉庫
方法1,直接遞歸clone
git clone git@github.com:jjz/pod-project.git --recursive
方法2,只clone了父模塊,要追加clone子模塊
git clone git@github.com:jjz/pod-project.git
cd pod-project
git submodule init
git submodule update
添加子模塊
已有的項目中添加子模塊步驟
git submodule add git@github.com:xxx/xxx-library.git xxx-library
git add .gitmodules xxx-ibrary
git commit -m "xxx-library submodule"
git submodule init
git submoudle update
刪除子模塊
cd pod-project
git rm --cached pod-library
rm -rf pod-library
rm .gitmodules
vim .git/config
# 刪除submodule相關的內容
# 比如
# [submodule "*"]
# url = git@github.com:jjz/**.git
git commit -a -m 'remove submodule'
參考
https://git-scm.com/book/zh/v1/Git-工具-子模塊
https://www.jianshu.com/p/9000cd49822c
https://www.jianshu.com/p/b49741cb1347
回滾場景
常見回滾場景
- 丟棄工作區的修改(沒有git add過),用命令
git checkout -- file
- 丟棄暫存區的修改(已git add過,沒有commit過),用命令
git reset HEAD <file>
- 丟棄本地倉庫的當前提交(已commit過,但沒有推到遠程倉庫),命令
git reset --hard commit_id
- 丟棄本地倉庫的當前提交(已推到遠程倉庫),並且覆蓋遠程倉庫提交歷史
# 下面兩個命令不建議,會被打
git reset --hard resetVersionHash
git push -f origin currentBranch
忠告:如果你的回退涉及到了遠程分支,在版本回退時最好使用revert,因它沒有修改版本歷史;如果使用reset,因為你的reset操作,會使你比遠程少了幾個提交,遠程會提示你落后於遠程版本,應該先git pull代碼,那么你的reset操作又有何意義呢?(git push -f 強推可以做到,但不推薦這樣做)
- 描述如下
假設一開始你的本地和遠程都是:
a -> b -> c
你想把HEAD回退到b,那么在本地就變成了:
a -> b
這個時候,如果沒有遠程庫,你就接着怎么操作都行,比如:
a -> b -> d
但是在有遠程庫的情況下,你push會失敗,因為遠程庫是 a->b->c,你的是 a->b->d
兩種方案:
push的時候用--force,強制把遠程庫變成a -> b -> d,大部分公司嚴禁這么干,會被別人揍一頓。
實踐方案如同4。
做一個反向操作,把自己本地變成a -> b -> c -> d,注意b和d文件快照內容一莫一樣,但是commit id肯定不同,再push上去遠程也會變成 a -> b -> c -> d
反向操作描述如下(建議操作):
- git log --pretty=online 顯示有三個版本
- git revert 版本號,抵消某個版本與其之后版本的修改,注意,這里的邏輯與git reset不一樣,如果想回到Second commit的版本,就需要抵消掉Third commit的修改。所以這里應該git revert Third commit的版本號
- revert的過程中可能會有沖突,git status查看沖突位置,解決沖突,git commit 文件名(無需git add)
- git log --pretty=online,Third commit並沒有丟失,而是多了一個revert版本,你可以 git log -p查看每個版本的修改,發現revert的版本所做的修改與Third commit恰恰相反,正好抵消掉了它的修改。
git reset commitID
是返回到指定commitID。
git revert commitID
是撤銷指定的commitID。
git撤回已add未commit的修改
也就是撤銷暫存區的修改。
git checkout .
git刪除未跟蹤文件
-
刪除 untracked files
git clean -f
-
連 untracked 的目錄也一起刪掉
git clean -fd
-
連 gitignore 的untrack 文件/目錄也一起刪掉 (慎用,一般這個是用來刪掉編譯出來的 .o之類的文件用的)
git clean -xfd
-
在用上述 git clean 前,牆裂建議加上 -n 參數來先看看會刪掉哪些文件,防止重要文件被誤刪
git clean -nxfd
git clean -nf
git clean -nfd
git merge了錯誤分支,如何優雅的回退到merge前的狀態?
當前master分支,小明和小王在中午12點分別新建了a b 分支。
1.小明在a分支,下午 1 3 5點分別提交了三個commit
2.小王在b分支,下午 2 4 6點分別提交了三個commit
3.小明在a分支,在下午7點執行了git merge b,此時commit的順序是1 2 3 4 5 6倒序,但是此時發現merge了錯誤分支,想回退到下午7點時的沒merge的狀態,即1 3 5commit狀態,如何優雅的進行git回退操作?
使用git merge --abort
。
從commit歷史,以及.git庫里移除掉某文件
通常是誤commit大文件導致不能push。
git push時終端報錯:
error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 Request Entity Too Large
fatal: The remote end hung up unexpectedly
你已經把大文件寫入本地.git歷史中。
你需要把它從commit歷史,以及.git庫里移除掉。
可以使用git filter-branch --tree-filter 'rm -f 文件名' HEAD
命令