git场景操作学习教程(二)
1、场景一
1.1、预置条件
- repo已经存在至少两个分支
- 在某一个分支上已经提交了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
命令解释
- 首先我们创建新分支;
- 然后我们回滚错误分支的提交,
HEAD~3
的含义是回滚3个commit,也就是撤销3次提交信息。 **注意这个命令因为加了--hard,所以它会丢失那些之前没有提交的修改。**如果你无法确定你要回滚多少次提交信息,或者回滚的提交信息很多,使用HEAD~
看起来比较麻烦,那么你可以使用Hash ID来回滚(每次提交都有对应的HASH值)。比如git reset --hard 6358612e5bcc27d0e29e4e0a66ae367814ab94b5
- 接着切换到新分支上,那些在错误分支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、预置条件
- 在github上你fork了别人的项目
- 别人的项目更新了很多新的commit
2.2、问题
你可能改了一些代码,打算提一个PR,于是为了避免冲突,你需要同步你fork的项目到别人的项目,那么应该如何操作呢?
2.3、操作步骤
- 首先要先确定一下是否建立了主repo的远程源:
git remote -v
如果里面只能看到你自己的两个源(fetch 和 push),那就需要添加主repo的源:
git remote add upstream URL
git remote -v
然后你就能看到upstream了。
- 如果想与主repo合并:
git fetch upstream
git merge upstream/master
2.4、命令解释
这个一目了然就不多说了
3、场景三
3.1、预置条件
- 在github上贡献代码
- 然后发现为什么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_NAME
和CORRECT_EMAIL
,之后再将这些重新修改的历史记录push到remote上:
git push --force --tags origin 'refs/heads/*'
4、场景四
4.1、预置条件
- 同一台电脑上有多个github账号、还有gitlab账号等
- 使用SSH登录认证github/gitlab
4.2、问题
有的时候你的电脑上有多人共用,那么每个人都有自己的github账号,或者他们还有gitlab账号,那么我们如何处理这种多账号多repo的情况呢?
4.3、操作步骤
解决这个问题的方法全在于SSH的config文件。假设现在有3个账号存在同一台电脑:
- github.com:test1:test1.git:id_rsa_test1.pub
- github.com:test2:test2.git:id_rsa_test2.pub
- 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会用到正确的公钥!
参考
公众号关注一波~
![微信公众号](https://blogimage.5udou.cn/homePage/%E5%85%AC%E4%BC%97%E5%8F%B7-%E7%99%BD%E8%89%B2%E7%89%88.png?x-oss-process=style/addWaterMarkBottom)
网站源码:linxiaowu66 · 豆米的博客
Follow:linxiaowu66 · Github
关于评论和留言
如果对本文 git场景操作学习教程(二) 的内容有疑问,请在下面的评论系统中留言,谢谢。