旨在记录在使用
git
过程中出现的一些问题和使用上的一些操作记录、或者是git
一些概念上的理解,防止重复踩坑。
1. 强制回滚远程git
仓库的某个提交
简单描述一下git
的操作流程:
- 工作区编写代码通过
add
命令添加到暂存区 - 暂存区通过
commit
命令添加到本地版本库 - 本地版本库通过
push
命令将本地代码推送到远程代码库
git reset --soft HEAD^
将本地仓库回滚为指定版本,且多余的提交回滚到暂存区
git reset --fixed HEAD^
将本地仓库和暂存区回滚为指定版本
git reset --hard HEAD^
将本地仓库、暂存区和工作区回滚为指定版本
强制回滚一个提交步骤:
- 拉取需要修改的分支代码
- 通过
git reset --hard HEAD^
命令回滚一个提交 - 通过
git push --force
强制推送到远程代码库
2. 在git
中~
和^
的区别
HEAD^
, HEAD^1
, HEAD~
三个表达式都表示HEAD
的父提交
HEAD^n
: 指的是HEAD
的第n
个父提交(有多个父提交的前提下[这里的父提交实际上是合并操作])HEAD~n
: 指的是HEAD
的第n
个祖先提交(这里需要区分父提交和祖先提交的区别),所以HEAD~n=HEAD^^^(n个^)
3. log
和reflog
的区别
reflog
: 可以查看所有分支的所有操作记录(包括已经删除的提交或者是重置的提交)log
: 不能查看被删除的提交
基于以上两个命令的区别reflog
在一些场景下可以提供一些妙用。
比如:
查看某个分支是基于那个分支迁出: git reflog --date=local | grep <分支名称>
1 | // 输出信息 |
4.revert
revert
是重做的意思,可以对推送到远程仓库的提交进行撤销。假设不小心将开发分支的功能合并到基线分支,这时就可以通过revert
命令进行撤销操作。
这里以gitlab
为例:
通过使用gitlab
进入需要撤回的merge
记录,选择右上角options->Revert
,这时会生成一个revert-xxxx
的分支,同时将该分支合并到基线分支,也就是将revert
提交合并到基线分支。
这时基线分支撤销之后,当开发分支的功能开发完毕后,将开发分支合并到基线分支,会发现部分代码丢失,而丢失的正是之前revert
操作撤销的那部分提交。所以只需要对之前的revert
操作再次进行revert
操作即可。简单来说就是负负得正的逻辑。
2023/07/24补充:
假设现在有两个分支的情况如下:master
表主线分支,dev
表开发分支
1 | init -> m1 -> m2 -> m3 (master) |
这时dev
分支以开发完成,所以将dev
分支合并到master
分支。
1 | init -> m1 -> m2 -> m3 -- merge commit1 (master) |
合并之后就会产生一个合并的提交,使用git log
命令可以看到这个提交信息。
1 | commit ced0a13d5d463b212a321f193ffb8f4608673920 (HEAD -> dev1, origin/dev1) |
这个合并之后开发分支还在继续开发dev
,同时其他开发完成的功能也会合并到master
分支。
1 | init -> m1 -> m2 -> m3 -- merge commit1 -> m4 -> merge commit2 (master) |
这时突然由于dev
分支合并到master
,导致master
出现了一些bug
,需要进行紧急回滚,但是不能将dev2
已经提交的合并回滚。
使用revert
命令,对merge commit1
这个提交进行回滚。这里会报错,这是因为git
在尝试撤销两个分支的合并的时候,不知道需要保留那个分支上的修改,git
提供了-m
命令来指定需要保留的分支修改。
-m
后面使用参数1
表示:表示保留当前分支的更改,使用参数2
表示:表示保留另一个分支的更改。
1 | git revert ced0a13d5d463b212a321f193ffb8f4608673920 |
这里我要保留master
分支的修改,也就是在master
分支的工作空间下执行-m 1
1 | git revert -m 1 ced0a13d5d463b212a321f193ffb8f4608673920 |
之后,git log
中就会多一个撤销的提交。
1 | commit f491e063ea4cd9fd4117eec888b29d7d4c45561a (HEAD -> develop, origin/develop) |
注意:之后,当dev1
分支上修复了这个bug,需要重新合并到master
之前,需要先将这个f491e063
提交revert
,这是因为revert
是通过添加提交的方式,撤销某个或者某些提交,它并不是删除提交,所以在将dev1
合并到master
之前,需要对之前撤销的提交执行撤销命令。
1 | git revert f491e063ea4cd9fd4117eec888b29d7d4c45561a |
这时又会产生一个新的提交:
1 | commit 6f7f80c2d28ae17ae8679f1dc543a9b65fdd8559(HEAD -> develop, origin/develop) |
revert
不仅可以对合并的提交
进行撤销,也可以对某个单独的提交进行撤销。
这里要有别于reset
,如果你使用这个命令作用于某个提交上:
1 | reset commitId |
它的意思是将这个提交之后的所有提交都移除,也就是这个提交之后的所有提交都删掉了,也就查不到这个提交之后的log
信息,这个命令用回滚这个词形容感觉更贴切。
当然reset
有它的应用场景,对于一些提交,由于各种原因推向远程仓库,可以通过reset
强制还原。点击查看reset
简单用法。
5.映射
命令:git remote add
shortname
:表示别名url
:表示远程仓库地址(http://xxx/xxx.git)
表示将远程仓库URL
映射成为本地仓库中对远程仓库的别名shortname
。默认情况下一般使用shortname=origin
。
可以通过git remote -v
查看对本地仓库设置的别名和远程仓库之间的关系:
1 | testname http://127.0.0.1:1000/xxx/xxx.git (fetch) |
6.推送
命令:git push <远程仓库名> <本地分支名>:<远程分支名>
git push -u origin master
:首次推送添加-u
参数,git
会将本地master
分支内容推送到远程的master
分支,同时将本地master
分支与远程master
分支关联,之后的推送仅通过git push
即可。(这里忽略了:<远程分支名>
的情况下,默认远程分支名与本地分支名一致)
7.跟换项目的远程仓库
1 | ##查看当前远程仓库 |