Git进阶之协作

解决Github merge 冲突问题

Posted by Bruce Zhao on July 14, 2016

Estimated reading time: 12 minutes. {Git} [Git]

目录

{: .no_toc}

上一篇的Git进阶关于fork的部分感觉没有弄明白,这次深入来了解一下,顺便解决一个merge中冲突问题。

案例

我要给revealjs 贡献代码,首先需要fork过来,然后做了好几个修改,create pull request。但是JJ Allaire 要我提交 standalone PR。 那我就需要建两个分支,分别修改然后提交PR。

revealjs 是rstudio基于reveal.js做的Rmarkdown生成炫酷html5 PPT的一个包,可以看看示例,下篇文章我会详细介绍一下如何用Rmarkdown做一个这么炫酷的ppt,点我体验

$ git clone git@github.com:BruceZhaoR/revealjs.git
$ git branch -b PR1

#完成修改后
$ git push origin PR1

补充知识:

git中存在upstream和downstream,简言之,这里我fork了rstudio/revealjs的master到brucezhaor/revealjs的master,这里的rstudio/revealjs:master就是brucezhaor/revealjs:master的upstream,而我的就是downsteam.这是一个相对关系,每一个本地分支都相对地可以有一个远程的upstream分支(注意这个upstream分支可以不同名,但通常我们都会使用同名分支作为upstream)。 初次提交本地分支,例如git push origin develop操作,并不会定义当前本地分支的upstream分支,我们可以通过git push --set-upstream origin develop,关联本地develop分支的upstream分支,另一个更为简洁的方式是初次push时,加入-u参数,例如git push -u origin develop,这个操作在push的同时会指定当前分支的upstream。

这里只是为PR,所以我觉得并不用定义upstream,直接去Github create pull request就可以了。

同理,做第二个standalone PR的时候需要切到主分支,然后在基于主分支建一个用于PR的分支。

$ git checkout master
$ git branch -b PR2

解决合并冲突

我自己在master上面修改了一些东西,然后我想把PR2合并到master里面来,我是在Github上面操作的,结果碰到了冲突,上面自动给出了使用命令行解决的方案:

# Step 1: From your project repository, bring in the changes and test.

$ git fetch origin
$ git checkout -b PR2 origin/PR2  #在本地创建和远程分支对应的分支
$ git merge master

# Step 2: Merge the changes and update on GitHub.

$ git checkout master
$ git merge --no-ff revealjs-3.3.0
$ git push origin master

补充知识:

--no-ff指的是强行关闭fast-forward方式。fast-forward方式就是当条件允许的时候,git直接把HEAD指针指向合并分支的头,完成合并。属于“快进方式”,不过这种情况如果删除分支,则会丢失分支信息,因为在这个过程中没有创建commit。

分支的同步与合并

fork的分支同步方法:

$ git remote add rstudio-revealjs git@github.com:rstudio/revealjs.git
$ git remote -v  #查看远程仓库
$ git fetch rstudio-revealjs master
$ git checkout master
$ git merge rstudio-revealjs/master  #碰到冲突可能需要手动解决

git branch --track rstudio rstudio-revealjs/master 建一个分支rstudio,用于跟踪rstudio-revealjs/master。还可以用git branch -u rstudio-revealjs/master rstudio,这里的rstudio是存在的分支,这个命名就是为本地存在的分支添加远程upstream。 这样只需要

git checkout rstudio
git pull  #从rstudio/revealjs:master同步过来
git push origin rstudio  #同步到自己的repository下面的rstudio分支

这样就建立了一个分支,专门用于同步被fork的项目了,这样别人项目更新了后,你只需要pull然后push就能更新,而且不需要commit。

小彩蛋

当我们commit后发现还有东西需要修改,但是又不想提交新的commit,这个时候需要用到git commit --amend。 具体做法是,继续修改,然后add,最后commit的时候的输入这个命令,然后就会把这次修改与上次修改合并为一个commit。但是,你会进入一个vim的编辑环境,这个时候需要记住一些命名才能玩的溜。

press "i" entering text;
press "o" start new line;
press "esc" ":wq" "enter" save and quit
press ":q" quit without save

版本回退


git log -3
git reset --hard HEAD^^
git reset --hard <hash>

git checkout -- filename  #撤销对工作区修改
git reset HEAD -- filename  # 清空add命令向暂存区提交的关于file文件的修改,使其变成unstage。

这篇文章是对之前一篇Git进阶的回顾,只留下实用的命名来完成任务,同时也是作为自己的参考与备忘。