前端git开发分支各种场景管理
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
命令
合乎自然而生生不息。。。