Git使用GitGit

git subtree相关问题

2018-08-07  本文已影响2人  Smileswlin

使用git subtree有一段时间了,主要用来解决多个项目共同使用相同代码的同步问题,特意简单整理了一下相关知识点以及使用过程中遇到的问题。

git subtree是什么?

git subtree 可以实现一个仓库作为其他仓库的子仓库。
subtree的核心思想与能做的就只有同步项目文件。

subtree本质就是把子项目目录作为一个普通的文件目录,对于父级的主项目来说是完全透明的,真的就是个普通目录,原来是怎么操作现在依旧是那么操作,就像操作主项目中其他文件一样的 add commit。

什么时候需要 subtree ?

1、当多个项目共用同一坨代码,而这坨代码跟着项目在快速更新的时候
2、把一部分代码迁移出去独立为一个新的 git 仓库,但又希望能够保留这部分代码的历史提交记录。

如何使用git subtree?

1.确保各个项目已经添加这个 remote(可选,方便后续用别名代替)
// git remote add  <S项目别名>  <S项目远程库仓库地址>
git remote add share http://xx.git
2.关联subtree(只需要执行关联操作git subtree add即可,无需对share项目执行git clone)
// git subtree add --prefix=<S项目的相对路径> <S项目远程库仓库地址 | S项目远程库别名> <分支> --squash
git subtree add --prefix=src/share share master --squash // 假设将share放在src目录下的
3. 提交更改到子项目
// git subtree push --prefix=<S项目的相对路径> <S项目远程库仓库地址 | S项目远程库别名> <S项目分支>
git subtree push --prefix=src/share share master

高阶:每次push命令都会遍历全部的commit,当你的项目越来越大,commit的数上来的时候,等待时间就会很长。--rejoin 避免了遍历全部commit的问题.

//git subtree split --rejoin --prefix=<S项目的相对路径> --branch <临时branch>
git subtree split --rejoin --prefix=src/share --branch srcTemp
//git push <S项目远程库仓库地址 | S项目远程库别名> srcTemp:master
git push share srcTemp:master
4.更新子目录:
// git subtree pull --prefix=<S项目的相对路径> <S项目远程库仓库地址 | S项目远程库别名> <分支> --squash
git subtree pull --prefix=src/share share master --squash

参考文章:
用 Git Subtree 在多个 Git 项目间双向同步子项目
Git Subtree的使用

git subtree 要不要使用 –squash 参数

使用 --squash 参数

优点:主项目的历史记录看起来还是比较整齐的。
缺点:在子项目需要 subtree pull 的时候,经常需要处理冲突,甚至每次 subtree pull 的时候都需要重复处理同样的冲突。
原因:subtree add/pull 操作中,需要用到 merge,而 merge 顺利进行的前提, 是要有相同的 parent commit。原子项目历史记录被合并后就消失了,相当于一个“新”的提交。 下次再进行 add/pull 时,新添加的内容找不到“上一次的修改”, 于是在更新 subtree 内文件的时候,就会提示冲突,需要手工解决。

不使用 --squash 参数

优点:子项目更新的时候,subtree pull 很顺利, 能够自动处理已解决过的冲突。
原因: 原子项目的历史复制到了父项目中, 下次再进行 add/pull 时,新增的 commit 能够找到“上一次的修改”, 那么他会像在子项目中逐个 am patch 那样更新 subtree 下的内容, 不会提示冲突。
缺点:子项目的更新记录“污染”了主项目的。

总结

是否使用 squash 都是可以的, 但需要在开始阶段作出选择,并 一直坚持下去 。 如果一会儿用一会儿不用,得到的不是两者的优点,而是两者的缺点之和。

既希望能够比较顺利的更新子项目, 又不希望子项目的历史记录直接合并在主项目中,请参考文章:
Git subtree 要不要使用 –squash 参数

git subtree使用过程中的问题&解决方案

问题1:执行提交操作不成功

$ git subtree push --prefix=src/share share master
 ! [rejected]        fc1de0e69c29fa1269feef734813f7889141859f -> master (non-fast-forward)
error: failed to push some refs to 'http://xxxx.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

解决方案:

// git push <your subtree's origin> `git subtree split --prefix=Path/to/subtree master`:master --force
git push share `git subtree split --prefix=src/share master`:master --force

问题2:执行了以上命令,又出现新的问题

$ git push share `git subtree split --prefix=src/share master`:master --force
To http://xxx.git
 ! [remote rejected] fc1de0e69c29fa1269feef734813f7889141859f -> master (Git:You are not allowed to force push code to a protected branch on this project.)
error: failed to push some refs to 'http://xxx.git'

解决方案:
进入git页面,按照以下路径,点击un-protext按钮解除保护,再重新执行上面的操作
project settings->protected branches-> click un-protect.g

问题3:执行更新操作不成功

$ git subtree pull --prefix=src/share share master
Working tree has modifications.  Cannot add.

解决方案:
项目有代码没提交,需要提交后才能执行pull

参考文章:
Git subtree - subtree up-to-date but can't push
Heroku deployment without the app being at the repo root (in a subfolder)
You are not allowed to push code to this project....! [remote rejected] master -> master (pre-receive hook declined)

原文:
git subtree相关问题

推荐文章:
前端开发之走进Vue.js(入门知识点)
快速掌握vue组件间的通讯
快速理解Vuex
如何在Vue+Webpack下配置Stylelint
Highchart属性笔记

上一篇下一篇

猜你喜欢

热点阅读