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

发表于 2016-12-11
更新于 2024-05-23
分类于 技术专栏
阅读量 2726
字数统计 4356

1、场景一

1.1、预置条件

  1. repo已经存在至少两个分支
  2. 在某一个分支上已经提交了3次commit

1.2、问题:

有时我们会发现代码commit错了分支,那么我们如何将在错误的分支上commit的代码转移到正确的分支上呢?

1.3、操作步骤:

这种情况下分为两种情况:

1.3.1、转移到全新的分支

git branch newbranch

git reset --hard HEAD~3

git checkout newbranch

git push origin develop
命令解释
  1. 首先我们创建新分支;
  2. 然后我们回滚错误分支的提交,HEAD~3的含义是回滚3个commit,也就是撤销3次提交信息。 **注意这个命令因为加了--hard,所以它会丢失那些之前没有提交的修改。**如果你无法确定你要回滚多少次提交信息,或者回滚的提交信息很多,使用HEAD~看起来比较麻烦,那么你可以使用Hash ID来回滚(每次提交都有对应的HASH值)。比如git reset --hard 6358612e5bcc27d0e29e4e0a66ae367814ab94b5
  3. 接着切换到新分支上,那些在错误分支commit的信息将会存在新分支上,所以你只需要push即可。

1.3.2、转移到已经存在分支

这种情况除了需要你要手动merge操作之外没有太大区别:

git checkout existingbranch
git merge master
git checkout master
git reset --hard HEAD~3 # Go back 3 commits. You *will* lose uncommitted work.
git checkout existingbranch

命令解释

这里大部分可以参考上面的,除了有一个困惑:那就是为什么已经存在的分支就需要执行merge操作?

大致解释一下:大家可以将git提交历史想象成一个树,然后你的每次提交都会让这个树不断长大,每一个分支都是指向这棵树的某一个节点,而当我们创建新的分支的时候,新分支将会指向这棵树的顶点也就是最新提交的地方。因此如果是转移到新分支,那么在我们新建分支的时候,新分支的commit就已经包含我们的那3次提交。如图所示:

但是如果你是转移到一条已经存在的分支,**那么这个已经存在的分支并没有指向最新的那3次提交,**于是这个时候如果你使用merge操作的,那么就等价于是将你这个已经存在的分支指到最新的这3次提交的那个节点上,这个时候你再去回滚那个错误的分支到这3次提交的节点之前才不会导致你丢失你这3次提交信息。

1.4、注意事项

注意:这种做法因为加了--hard,所以它会丢失那些之前没有提交的修改。

1.5、附加方法

你也可以使用git cherry-pick方法。cherry-pick可以将提交转移到目标分支然后复位源分支。

git checkout target
git cherry-pick source
git checkout source
git reset --hard source^

如果你想要转移的commit不是最后提交的,你不得不使用git rebase -i而不是刚才的最后一条命令git reset,然后选择给你cherry-pick使用的指定的commit名字。该命令具体参考:

https://git-scm.com/docs/git-cherry-pick

2、场景二

2.1、预置条件

  1. 在github上你fork了别人的项目
  2. 别人的项目更新了很多新的commit

2.2、问题

你可能改了一些代码,打算提一个PR,于是为了避免冲突,你需要同步你fork的项目到别人的项目,那么应该如何操作呢?

2.3、操作步骤

  1. 首先要先确定一下是否建立了主repo的远程源:git remote -v 如果里面只能看到你自己的两个源(fetch 和 push),那就需要添加主repo的源:
git remote add upstream URL
git remote -v

然后你就能看到upstream了。

  1. 如果想与主repo合并:
git fetch upstream
git merge upstream/master

2.4、命令解释

这个一目了然就不多说了

3、场景三

3.1、预置条件

  1. 在github上贡献代码
  2. 然后发现为什么contributors没有自己的账号呢?

3.2、问题

贡献了很多代码,有时候会发现commit的数量貌似和平时自己的代码提交数量不一致,然后仔细发现才看到commit使用的邮箱和你的github账号的邮箱不一致,那么这时候有什么挽救的办法吗?

3.3、操作步骤

一旦有这种情况,那么我们只能重写整个repo的历史提交记录的邮箱来更改错误,这种做法不建议使用在不属于你自己的repo上。

提供下面的脚本来修改:

#!/bin/sh
git filter-branch --env-filter '
OLD_EMAIL=""
CORRECT_NAME=""
CORRECT_EMAIL=""
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags


你只需要找到你之前提交的错误邮箱,然后填写OLD_EMAIL字段,同时填写你的新邮箱和用户名到CORRECT_NAMECORRECT_EMAIL,之后再将这些重新修改的历史记录push到remote上:

git push --force --tags origin 'refs/heads/*'

4、场景四

4.1、预置条件

  1. 同一台电脑上有多个github账号、还有gitlab账号等
  2. 使用SSH登录认证github/gitlab

4.2、问题

有的时候你的电脑上有多人共用,那么每个人都有自己的github账号,或者他们还有gitlab账号,那么我们如何处理这种多账号多repo的情况呢?

4.3、操作步骤

解决这个问题的方法全在于SSH的config文件。假设现在有3个账号存在同一台电脑:

  1. github.com:test1:test1.git:id_rsa_test1.pub
  2. github.com:test2:test2.git:id_rsa_test2.pub
  3. gitlab.com:test3:test3.git:id_rsa_test3.pub

上面的格式是:主机名:用户名:仓库名:公钥文件

公钥的生成以及添加就不细说了,可以参考:获取Git代码的两种方式

那么你应该在你的~/.ssh/文件夹下添加config文件,内容如下:

Host test1
  HostName github.com
  IdentityFile ~/.ssh/id_rsa_test1

Host test2
  HostName github.com
  IdentityFile ~/.ssh/id_rsa_test2
  
Host test3
  HostName gitlab.com
  IdentityFile ~/.ssh/id_rsa_test3

有了这么一个文件,当我们使用git@Host:Repo这种类型的URL的时候,SSH会根据config配置的文件去找对应的公钥。比如:

git clone git@test1:test1/test1.git

这个时候SSH会找到Host为test1的配置参数,然后就可以获知其HostName:github.com,所以其命令等价于:

git clone git@github.com:test1/test1.git

但是因为有指定的认证公钥,所以会去加载正确的公钥,于是认证成功。

上面的情况是针对github上已经存在的repo。

如果是初始化仓库的话,那么正常的流程除了github上所列举的,需要改动下面这个命令:

git remote add origin git@github.com:test1/test1.git

为:

git remote add origin git@test1:test1/test1.git

这样才能保证你的origin会用到正确的公钥!

参考

  1. https://git-scm.com/docs/git-cherry-pick
  2. http://stackoverflow.com/questions/1628563/move-the-most-recent-commits-to-a-new-branch-with-git
  3. https://segmentfault.com/q/1010000002590371

公众号关注一波~

微信公众号

关于评论和留言

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

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

Follow:linxiaowu66 · Github