git场景操作学习教程(一)

发表于 2016-09-24
更新于 2024-05-23
分类于 技术专栏
阅读量 6516
字数统计 5319

1、场景一

预置条件:

  1. 远端服务器已有master和develop分支

  2. 使用git flow来进行代码开发

问题:

如何pull develop分支并开始使用git flow进行代码管理?

操作步骤:

1. git clone ...
2. git checkout develop
3. git flow init

命令解释:

  1. 使用git clone pull下来的代码是远端的master分支。

  2. 因为远端还有develop分支,所以我们可以使用checkout命令。在官方文档中可以找到这句话:

    If is not found but there does exist a tracking branch in exactly one remote (call it ) with a matching name, treat as equivalent to

    $ git checkout -b <branch> --track <remote>/<branch>

也就是说当前本地不存在develop分支,但是远端存在,所以使用这个命令就等价于新建develop分支,然后将本地的develop分支追溯于远端的develop分支,也就是二者关联起来。

  1. 之后本地存在master和develop分支,便可以使用git flow init。之后的操作便可以参考另外一篇博客:git-flow工具之命令行操作教程

2、场景二

预置条件:

  1. 远端服务器已有master和develop分支

  2. 使用git flow

  3. 本地进行feature开发,并且已经提交了2个commits

  4. 远程develop因为别的同事代码的提交从而比本地的develop分支提前了几个版本

问题:

那么此时如何安全地提交feature分支的代码到远端develop分支呢?

操作步骤:

这种情况需要分为两种:有冲突与无冲突。

无冲突

假设当前在feature/ft-1分支上:

1. git pull origin develop:develop
2. git flow feature finish

或者:

1. git checkout develop
2. git pull origin develop
3. git flow feature finish ft-1
命令解释
  1. 无论是git pull origin develop:developgit pull origin develop都是为了将本地的develop分支与远端的develop分支同步,区别就在于你是出于哪个分支。
  2. 如果你是在feature/ft-1分支上,那么你的命令一定得补齐分支的名称,即develop:develop,否则会认为你是将远端的develop分支拉取到本地的feature/ft-1上,这样等于你的develop分支依然没有与远端develop分支同步,当再执行git flow feature finish的时候必然会报错:
Branches 'develop' and 'origin/develop' have diverged.
Fatal: And branch 'develop' may be fast-forwarded.

所以这时你还是需要重新同步本地的develop分支。这个时候的情形就类似于后面的第二种操作方法。

Tips:

git pull这条命令集成了两个操作步骤:git fetchgit merge FETCH_HEAD,这样的话git便会帮你自动merge代码,如果有冲突便会报错。如果你不想自动执行git merge那么加上参数--rebase,便会改成自动执行git rebase。至于二者区别稍后再说。

有冲突

当使用git pull 命令的时候出现conflicts的概率很大,一般报错如下:

error: Your local changes to the following files would be overwritten by merge:
        README.md
Please commit your changes or stash them before you can merge.
Aborting

这个时候你有3种方法来解决冲突:

方法一

  1. git commit -am 'add test'
  2. git pull
  3. solve the conflicts
  4. git commit -am 'solve the conflicts'
  5. git push

方法二

  1. git stash
  2. git pull
  3. git stash top
  4. git commit -am 'add test'
  5. git push

方法三

此方法只适用于你不想保存本地的change的时候: git reset --hard

3、小知识点

3.1. git remote add origin url

该命令是提供了URL的alias,配置如上之后只需要使用origin就等价于使用上述URL,所以你可以将origin换成任何你想要的名字,origin只是大家一种惯用的标记罢了。我们可以参考.git/config来验证:

[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
[remote "origin"]
	url = https://github.com/linxiaowu66/testtest.git
	fetch = +refs/heads/*:refs/remotes/origin/*

3.2. git push -u origin master

该命令是将本地的master分支推送到远端的master分支,其中加-u的命令是为了将本地的分支track到远端的分支,也就是说建立二者之间的关系。所以有如下提示:

Branch master set up to track remote branch master from origin.

如果你不使用-u选项,那么将会有两个不同点:

  1. .git/config下不会有下面这个配置:
[branch "master"]
        remote = origin
        merge = refs/heads/master
  1. 当再使用git pull的时候会报错:
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> master

所以加上-u之后,你就可以不使用确切的命令git pull origin master即可同步local和remote。

3.3. git rebase

rebase的用途官网上是这么说的:Reapply commits on top of another base tip。简单直译过来就是重新应用提交的信息到另外一个基准点的上面。

基本命令是:

git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
	[<upstream> [<branch>]]
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
	--root [<branch>]
git rebase --continue | --skip | --abort | --edit-todo

参考官网的解释我们说一下其原理:

查看第一条命令知道<upstream><branch>是可选的,如果只出现一个那必然是<updtream>。所以

如果没有指定branch参数,那么默认是在当前分支上rebase,如果指定的话,那么会执行的第一个动作就是git checkout <branch>

如果没有指定<upstream>的话,那么upstream的配置就从branch.<name>.remote branch.<name>.merge选项中获取。如果你当前不再任何分支上或者如果当前分支没有配置一个<upstream>的话,那么rebase将会终止。

然后当前分支上的所有提交的改动(这些改动没有体现在)会被保存到一个临时的区域。

接着该分支会被复位到<upstream>的状态或者<rebase>(如果--onto选项有提供的话),这个如同操作git reset --hard <upstream>(<newbase>)命令一样。ORIG_HEAD被设置为指向了该分支reset之前的提交信息的顶部。

那些被保存到临时区域的提交将会按照顺序(或者你指定的顺序)一个一个地重新提交到当前的分支。

如果rebase的时候merge失败,那么该过程将会停止下来然后等待你进行手工解决冲突然后再继续运行git rebase --continue

说了这么多,举个小例子:

假设当前是在develop分支上,并且master分支和develop分支已经提交了几个各自的commits:

接着我们对develop分支进行rebase,于是将develop分支的提交改动缓存起来,然后将该分支复位到master的状态下,然后再从新的状态下将这些commit重新提交到该分支下,这个时候develop分支就可以在保持最新的状态下又能有自己的本地改动,如此超赞的功能也就git才有的!!!

rebase之后的历史图:

再放两张提交有用rebase和没有rebase的区别,不知道童鞋们能看出区别吗?

使用gitk查看的结果

使用tortoiseGit查看的结果

友情提示

这一系列的文章还有,以后在工作中遇到别的场景会继续补充的,敬请期待~~~~~

参考links

  1. https://git-scm.com/docs
  2. https://blog.yorkxin.org/2011/07/29/git-rebase

公众号关注一波~

微信公众号

关于评论和留言

如果对本文 git场景操作学习教程(一) 的内容有疑问,请在下面的评论系统中留言,谢谢。

网站源码:linxiaowu66 · 豆米的博客

Follow:linxiaowu66 · Github