之前的多人项目大多使用了SVN作为版本控制,自己只会用eclipse连接GitHub的操作。这次项目采用了git作为版本控制系统,所以学会了很多新操作,这里权当记录,以备后用。
git的一些基本操作可参考http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html
简而言之就是:
git fetch
git merge
git merge [分支]
git push
git branch [新分支]
git checkout [file] 不保留此文件的修改,退回上次commit
git checkout . 不保留所有文件的修改,退回上次commit
git checkout [branch] 切换分支
git branch -d [分支] 删除分支
git remote -v 查看remote
git log 查看版本
git log --stat 查看版本详细信息
git reset [版本号,通过log获取] 退回版本到版本
git rebase [branch] 取消自己所做的更改并记录,将目标分支pull过来,然后在此基础上重复自己的更改记录,和git merge最大区别是指针指向。详情参考http://blog.csdn.net/hudashi/article/details/7664631/
在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决 冲突;在解决完冲突后,用"git-add"命令去更新这些内容的索引(index), 然后,你无需执行 git-commit,只要执行:
这里写出若干个常用场景:
0、忽略乱七八糟的文件
用git的时候总有些什么classpath等文件被不小心传上remote(尤其是elipse直接share的时候),别人下载下来也是带着classpath文件的,但是每个人的classpath其实是不一样的,所以每次提交的时候会发现有classpath文件已更新,这东西还不能删了,删了之后别人再用eclipse pull的话会导致工程出现问题。所以干脆自己忽略好了:
a) gitignore文件:这个解决方法在文件没被追踪的时候加入到此文件,则可以忽略此文件,但是已经追踪的再加入就无效了。
b) git rm--cache 文件:这个命令可以在不删除本地文件的条件下删除追踪,但是对于classpath这种删完别人会出错的东西不适用,因为其他人pull的时候会把他本地的classpath删了。。。
c) git update-index --assume-unchanged docMining/.classpath:这种方法相当于在本地忽略了classpath更新,提交和更新时都会忽略这个文件,不想麻烦的每个人都重建一遍工程的话可以在发生冲突的机器执行这个命令。如果想取消忽略使用如下命令:git update-index --no-assume-unchanged docMining/.classpath
1、git解决冲突
使用git mergetool 命令可以打开冲突文件,修改后git commit即可保存为一个合并后的文件。合并后出现的,orig文件删除即可。
2、git subtree
在这里我有一个工作场景如下:
我的一部分个人代码托管在了github上,现在这部分代码要作为一个多人工程的一个依赖工程,个人工程内的许多类和方法多人工程要用到。我又不想这两个版本分别维护,毕竟分别维护的成本很高,但是又要保证两边代码一致并且和两个remote一致,一个是自己搭建的git另一个是github。
这种情况svn比较难以解决,但是git还算方便,可以使用git subtree命令来实现。
首先说一下git subtree的工作过程,我们通过创建一个subtree将个人工程当成一个子工程拷贝到我们多人工程的工作空间内
git subtree add --prefix=子项目相对于多人项目的相对路径 子项目的地址(可以指定本机的.git文件夹,或者远程的.git,如github) 多人工程的某分支
如git subtree add --prefix=segmentation/ ../../eclipse/workspace/segmentation/segmentation/.git master
需要注意的是--prefix一定要指定相对路径,在windows下以/开头或者以D:开头会直接报错,路径不能创建
也就是说我们还是相当于有两份这个工程,也需要保证两个工程的一致性,但是不必手动管理,可以使用git维护两个工程:
git subtree pull --prefix=子项目相对于多人项目的相对路径 子项目的地址(可以指定本机的.git文件夹,或者远程的.git,如github) 多人工程的某分支 如git subtree pull --prefix=segmentation/ ../../eclipse/workspace/segmentation/segmentation/.git master
这样我在个人代码中进行的修改就可以同步到多人工程的master项目下了,当然,是从远端的master同步到本地的master下。
git subtree pull --prefix=子项目相对于多人项目的相对路径 子项目的地址(可以指定本机的.git文件夹,或者远程的.git,如github) 个人工程的某分支
git subtree push --prefix=segmentation/ ../../eclipse/workspace/segmentation/segmentation/.git hotfix
需要注意的是,最好Push到一个不存在的分支,不然有可能会有奇怪的问题,个人工程会进行恢复操作,还得使用git checkout .来保证更新,而push到一个不存在的分支则直接可以git merge hotfix就行
这样就可以在两个工程之间进行相互同步了。
杂谈:
在搜索git子模块的过程中git submodule和repo被反复提及,https://codingkilledthecat.wordpress.com/2012/04/28/why-your-company-shouldn't-use-git-submodules/
上述文章阐明了为什么不考虑使用submodule,并且建议在提到的另外几种子模块中挑选一种进行使用,然而在git-scm上的book中,第一版介绍了submodule和subtree,第二版只介绍了submodule,所以究竟哪个更好显得不是那么明确。目前我本人的需求来讲git subtree能实现的非常完善,但是以后需求变化了可能会尝试使用其他命令。