zhengrenzhe's blog   About

协同开发时的一些git操作

来豆瓣也快一个月了,在这段时间中经常被git各种虐。单人/几个人的情况下,git的用法非常简单,无非就是按照google出来的那些workflow进行操作,但是在较多人开发同一个产品时,基本的workflow就无法应付了,需要使用git更高级的操作,下面总结下我遇到的一些多人开发情况下的高级git操作。

项目开始

这部分与基本的workflow相似,一般都是由项目负责人在代码托管平台上创建项目,其他开发人员Fork这个项目到自己的仓库里,新开分支,在这个分支中进行开发,开发完成后发送Pull Request (PR)到主项目分支中,待项目负责人合并pr后,就算完成了。

提交

如果经常需要提交,但每次的提交只是改动很少或只是测试的话,那在提交时不应该运行git commit -m "xxx",这样会造成很多无意义的commit,应该只保留一些有意义,修改较多的提交,这是就要使用git commit --amend。这个命令会将当前修改和并进上一次commit中,也就是修改了上一次commit的内容,这样虽然是在不停的commit,但实际上只产生了了一个commit。使用--amend命令后,push需要带上-f选项。

git add .
git commit -m "修改xxx"
git push origin develop

// ... 修改等操作

git add .
git commit --amend
git push origin develop -f

// ... 修改等操作

git add .
git commit --amend
git push origin develop

// ...

合并提交

当已经提交过多次,git看着非常杂乱时,可以将之前的commit合并为一个。 首先使用git log命令查看提交历史的SHA-1 校验和,比如像下面这样:

可以看到最新的提交在最上面,较老的依次向下。 这里使用git rebase -i命令进行合并,该命令后跟某次较老的commit的SHA-1 校验和,之后这条commit之前的commit就会被合并,这些被合并的commit会产生一个新的commmit。假设这里我们要合并97e1402这条之前的commit,可以这么做:

git rebase -i 97e14028bf5bcaa68e4569a0ad001cdc974424af

之后会调用vim,出现这样一个界面: 这时commit的显示顺序又倒过来了,这时要合并之前的commit,把底下三个commit前面的commit变成s,这样git就知道我要这些commit,但是把它们合并到之前的commit里去,这样就完成了合并commit。 要注意的是,git rebase -i 后面根这个SHA-1 校验和所在的commit并不会被合并,而是合并这条之后的(commit时间比这条晚的)。

标记界面如下图:

保存退出vim后会再次调用vim,让你修改这些commit的说明,把不需要的删掉就好了,就像下面这样:

现在就合并完了,再次运行git log

可以看到,刚才的97e14028那条commit没有被合并,而这条之前的所有commit被合并了,而且生成了一个新的commit f9214c6ad,这样commit就合并完了。

远程库

当一个项目被clone到本地后,它默认配置有一个远程库,就是你clone的那个远程库,通过 git remote -v可以看到当前本地仓库所配置的远程库的信息。

在多人开发的情况下,本地仓库的远程库会有多个,比如还会添加主项目的远程库地址,用来同步最新代码。添加其他远程库时,使用git remote add 自定义名字 远程地址命令来添加其他远程库。

git remote add test2 git@gitcafe.com:ZhengRenZhe/test2.git

再次运行git remote -v,可以看到新添加的远程库。

从远程库获取代码

当要获取远程库中有的,而本地仓库没有的文件时,可以使用git fetch命令来获取。我在test2远程库中新建了test.md文件,现在我要在本地仓库中获取它。

git fetch test2

这时我已经获取到了test2远程仓库中的文件。

但看一下本地的文件,并没有test.md这个文件,这是为什么呢?因为从test2远程库中获取的代码并没有在我当前的master分支里,而是在test2/master这个分支里,要把它应用在当前的master分支里,还需要使用git pull命令手动合并分支。

git pull test2 master

后面的两个参数分别是要被合并的远程库名(本地的)和分支名。运行后,会调用vim,让你填写本次的说明,完成后退出vim,分支就合并好了,test.md文件就到了当前master分支里,再次查看本地目录就能看见这个文件啦。

从远程库获取代码2

但是,从远程库中获取代码并不是只有这一个命令。当设置了某个分支用于跟踪某个远程库的分支时,直接使用git pull命令就能获取远程库中的更新,作用与fetch后再合并分支相同,与fetch不同的是它会自动合并到本地的当前分支。

当使用git clone命令从远程库下载代码后,本地的master分支将自动跟踪远程库中的master分支,所以在clone后直接使用pull就能获取最新代码。

上游与upstream

在多人开发时,fork完主库,在clone到本地,这时你的本地remote地址是只有你fork了的项目的地址的,但你要经常保持本地库与项目主库代码的同步,所以要添加项目主库的地址,前面已经说过,使用git remote add命令添加,而这个主库,就是当前fork了的项目的上游。在添加主库地址时,通常将它命名为upstream。

rebase

rebase是一个很好用的东西,他的作用是帮你整合分支的。 在多人开发情况下,你从项目仓库fork了一个你自己的开发仓库。假设主分支名为master,在他的基础上又新开了一个名为dev的开发分支,当过了几天,你在dev分支上开发的功能上开发完成后,要向主库发起pr。在最后提pr前,你需要同步一下主分支的最新代码。如果不使用rebase,在当前开发分支直接同步主库最新代码的话,虽然这确实能获取到最新代码,但是这会产生一个新的commit。而使用rebase的话,就完美了,这会使你的分支很干净。具体使用步骤为:先checkout到主分支,比如master,在master分支下获取最新代码,用fetch或者pull都可以,之后再checkout到你的开发分支下,运行

git rebase -i master

这样就不会多出来一个commit,同样也获取了代码,也保持了分支的干净。

← ES6解构赋值总结  Javascript的cloneNode →