经常会听到别人说,如果时光可以倒流,我将会如何如何,可是现阶段的科技还达不到时光倒流的目的,或许在《三体》世界的四维裂缝里可以试一下。现实的世界中找不到后悔药,但是在代码的世界里却可以轻松实现,错误的BUG修改、砍掉的做了一半的功能都可以轻松回退,不留一丝痕迹,回滚之后一切又可以重新开始了。
大型编程项目的开发往往伴随着版本工具的使用,其实引入代码版本控制工具,有一部分原因也是为了方便回退,回退操作每天都发生的,只是有时是我们显式的操作,有时却自然而然的进行着,我们切换着分支很可能就是从开发版本回退到一个稳定版本,我们查询日志,实际上是在记忆上回退我们整个的开发过程,找寻其中的问题和修改的内容。
Git
的使用中,由于一个文件存在好几种状态的变化,所以处理起回退要分情况进行,有些各式各样的命令最终分析起来其实作用是一样的。
版本库就是文件修改的目的地了,最终的修改会提交到版本库,这时提交的文件状态变成 committed
,其实也是一种 unmodified
状态,一路走来,版本库中记录了你的每一次提交,可以追溯你每一次修改的内容。
其实还有一个远程仓库的概念,一般确定本地仓库的修改没有问题了,或者要将本地代码远程备份时,可以将自己修改的分支推送到远程仓库,因为有时候我们也想回退已经推送到远程仓库的修改,所以这里先提一下远程仓库。
总结起来一个文件的状态通常可以分为:
untracked
状态modified
状态staged
状态committed
状态unmodified
状态上面提到了在 Git
这个版本控制工具下文件的各种状态,其实回退操作就是通过命令实现这些文件状态的“倒退”,进而达到回退操作的目的,下面一起先来了解下这些可以实现回退的命令。
这个命令又出现了,上次是总结 git branch
分支操作的时候,git checkout
可以用来新建或者切换分支,这次总结回退版本的命令,git checkout
也可以用来回退文件版本,很神奇吧。
其实这个命令的作用就是它单词的本义——检出,他的常用操作也取自这个意思,比如 git checkout branch_name
切换分支操作,实际上就是把指定分支在仓库中对应的所有文件检出来覆盖当前工作区,最终表现就是切换了分支。
而针对于文件的检出可以使用 git checkout -- file_name
,当不指定 commit id
就是将暂存区的内容恢复到工作区,也就可以达到回退本地修改的作用。
不过,这个身兼数职的 git checkout
命令现在可以轻松一些了,从 Git 2.23
版本开始引入了两个新的命令: git switch
用来切换分支,git restore
用来还原工作区的文件,这个后面还会提到。
revert 这个词的意思是:归还,复原,回退,它和后面即将提到的 restore 在意思上简直无法区分,为了区别他们两个这里可以把 git revert
看成归还的意思,对某次提交执行 git revert
命令就是对这次修改执行一个归还操作,其实就是反向再修改一次。
要理解 git revert
就要从反向修改的含义来看,当我们再一个文件中添加一行内容,并提交到版本库后,产生一个提交id——commit-id-a
,如果这时使用 git revert commit-id-a
命令,就相当于在工作区中的那个文件将刚在新加的一行内容删除掉,然后再进行一个提交。
注意,这个操作是会改变分支记录的,因为产生了新的提交。
这个命令是 Git 2.23
版本之后新加的,用来分担之前 git checkout
命令的功能,作用就是用暂存区或者版本库中的文件覆盖本地文件的修改可以达到回退修改的目的,同时也可以使用版本库中的文件覆盖暂存区的文件,达到回退git add
命令的目的。
注意,这个操作是不会影响分支记录的,就是相当于之前的 git checkout
命令重新检出一份文件来覆盖本地的修改。
reset 重新设置的意思,其实就是用来设置分支的头部指向,当进行了一系列的提交之后,忽然发现最近的几次提交有问题,想从提交记录中删除,这是就会用到 git reset
命令,这个命令后面跟 commit id
,表示当前分支回退到这个 commit id
对应的状态,之后的日志记录被删除,工作区中的文件状态根据参数的不同会恢复到不同的状态。
--soft
: 被回退的那些版本的修改会被放在暂存区,可以再次提交。
--hard
: 被回退的那些版本的修改会直接舍弃,好像它们没有来过一样。
这样来看,git set
命令好像是用来回退版本的,但是如果使用 git rest HEAD file_name
命令就可以将一个文件回退到 HEAD
指向版本所对应的状态,其实就是当前版本库中的状态,也就相当于还原了本地的修改。
临时插播的命令,本来删除不能算是回退,但是如果它和某些命令反着来就是一种回退,比如对一个新文件使用 git add newfile_name
命令,然后再使用 git rm --cached newfile_name
就可以将这个文件从暂存区移除掉,但是在工作区里没有消失,如果不加 --cached
参数,就会从工作区和版本库暂存区同时删除,相当于执行了 rm newfile_name
和 git add new_file
两条命令。
albert@homepc MINGW64 /d/gitstart (dev)
$ ls
README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
nothing to commit, working tree clean
albert@homepc MINGW64 /d/gitstart (dev)
$ git branch -a
* dev
master
remotes/origin/dev
remotes/origin/master
albert@homepc MINGW64 /d/gitstart (dev)
$ git branch -vv
* dev 3226b63 [origin/dev] add readme file
master 3226b63 [origin/master] add readme file
实话实说,办不到,没有加到过暂存区就没有被追踪,它的任何修改是没有办法回退的,可是使用 Ctrl+Z
碰碰运气,没准就退回到了你想要的状态。
git add
操作这种情况可以使用git rm --cached newfile
、git restore --staged newfile
或者 git reset HEAD newfile
命令,使用后两个命令的时候不能是版本库的第一个文件。
albert@homepc MINGW64 /d/gitstart (dev)
$ echo "test data">new.txt
albert@homepc MINGW64 /d/gitstart (dev)
$ git add new.txt
warning: LF will be replaced by CRLF in new.txt.
The file will have its original line endings in your working directory
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: new.txt
albert@homepc MINGW64 /d/gitstart (dev)
$ git rm --cached new.txt
rm 'new.txt'
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
new.txt
nothing added to commit but untracked files present (use "git add" to track)
albert@homepc MINGW64 /d/gitstart (dev)
$ git add new.txt
warning: LF will be replaced by CRLF in new.txt.
The file will have its original line endings in your working directory
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: new.txt
albert@homepc MINGW64 /d/gitstart (dev)
$ git restore --staged new.txt
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
new.txt
nothing added to commit but untracked files present (use "git add" to track)
albert@homepc MINGW64 /d/gitstart (dev)
$ git add new.txt
warning: LF will be replaced by CRLF in new.txt.
The file will have its original line endings in your working directory
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: new.txt
albert@homepc MINGW64 /d/gitstart (dev)
$ git reset HEAD new.txt
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
new.txt
nothing added to commit but untracked files present (use "git add" to track)
git add
操作我们直接修改 README.md 文件吧,删除刚才添加的未受版本管理的 new.txt,在 README.md 文件中添加内容,然后试着还原,这种情况常常出现在修改一个功能还未提交,但是先不要求修改了,可以直接还原。
albert@homepc MINGW64 /d/gitstart (dev)
$ echo "new line">>README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
albert@homepc MINGW64 /d/gitstart (dev)
$ git restore README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
nothing to commit, working tree clean
albert@homepc MINGW64 /d/gitstart (dev)
$ echo "new line">>README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
albert@homepc MINGW64 /d/gitstart (dev)
$ git checkout -- README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
nothing to commit, working tree clean
albert@homepc MINGW64 /d/gitstart (dev)
$ echo "new line">>README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
albert@homepc MINGW64 /d/gitstart (dev)
$ git reset --hard HEAD README.md
fatal: Cannot do hard reset with paths.
albert@homepc MINGW64 /d/gitstart (dev)
$ git reset --hard HEAD
HEAD is now at 3226b63 add readme file
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
nothing to commit, working tree clean
git add
操作使用了 git add
命令之后,文件的改变就放到了暂存区,这种情况可以使用git restore --staged file_name
或者 git reset HEAD file_name
命令。
执行 git restore --staged file_name
实际上是使用版本库中的文件覆盖暂存区中的数据,执行结束后文件状态变成了 <还原02>
中的情况。
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
nothing to commit, working tree clean
albert@homepc MINGW64 /d/gitstart (dev)
$ echo "test add">>README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
albert@homepc MINGW64 /d/gitstart (dev)
$ git add README.md
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git restore --staged README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
albert@homepc MINGW64 /d/gitstart (dev)
$ git add README.md
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git reset HEAD README.md
Unstaged changes after reset:
M README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
git add
、git commit
操作git commit
命令一旦执行了之后就形成了“历史”,我们叫做提交日志,要想回退就得有篡改历史的能力,很幸运 Git
给了我们这种能力,其实提交之后我们可以把本地文件反向修改,然后再提交一次,但是我们说的还原,一般都是只倒退,既然是错误的提交,我们就像把这段“历史”抹去,这时就要用到 git reset HEAD^
命令。
执行这个命令之后,刚刚的提交记录就被抹掉了,文件状态就回到了 <还原02>
的情况,如果加上参数 --soft
就会回到 <还原03>
的情况,如果加上参数 --hard
,就不能添加 file_name
这个文件名,然后整个工作区倒退到上一次修改之前,其他两种参数 --mixed
和 --soft
就可以指定添加名字。
这里的 HEAD^
表示最新版本的前一版,也就是倒数第二版本,可以类推,HEAD^^
表示倒数第三版本,HEAD^^^
表示倒数第四版本。
另外还有另一种写法 HEAD~1
表示最新版本的前一版,也就是倒数第二版本,HEAD~2
表示倒数第三版本,HEAD~3
表示倒数第四版本。
其中 ^
和 ~
的含义并不相同,涉及到合并分支的概念,有兴趣的话可以多了解下,这里就不展开了,继续还原当前这种情况,我们选择 git reset HEAD^
命令,先提交看下:
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
albert@homepc MINGW64 /d/gitstart (dev)
$ git add README.md
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory
albert@homepc MINGW64 /d/gitstart (dev)
$ git commit -m"modify readme 1"
[dev 8a40f22] modify readme 1
1 file changed, 1 insertion(+)
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is ahead of 'origin/dev' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
albert@homepc MINGW64 /d/gitstart (dev)
$ git log -2
commit 8a40f229881da037ff99070fa205d7819ba9f51b (HEAD -> dev)
Author: albert <qianxuan101@163.com>
Date: Sat Mar 7 15:46:32 2020 +0800
modify readme 1
commit 3226b63185a16398a02d5eaea47c95309ba49588 (origin/master, origin/dev, release, master)
Author: albert <qianxuan101@163.com>
Date: Wed Feb 26 00:36:35 2020 +0800
add readme file
然后再还原试试:
albert@homepc MINGW64 /d/gitstart (dev)
$ git reset HEAD^
Unstaged changes after reset:
M README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
albert@homepc MINGW64 /d/gitstart (dev)
$ git log -2
commit 3226b63185a16398a02d5eaea47c95309ba49588 (HEAD -> dev, origin/master, origin/dev, release, master)
Author: albert <qianxuan101@163.com>
Date: Wed Feb 26 00:36:35 2020 +0800
add readme file
怎么样,历史被我们抹除了,需要注意的是,如果想还原“历史”,那么 git set
命令后面不能跟文件名,也就是说必须整个还原到上一版本,否则就相当于将单个文件简单反向修改添加到暂存区,而之前对文件的修改保留在本地,文件的日志并没有回退,具体的文件状态还得你自己操作感受一下。
git add
、git commit
、git push
操作这种情况就是还原远程仓库的日志记录了,实际上操作步骤先按照 <还原04>
来处理,然后将本地分支情况推送到远程分支即可。
我们先把刚才的修改提交,然后推送到远程分支,使用 git status
可以看到本地分支已经领先远程分支了(Your branch is ahead of ‘origin/dev’ by 1 commit.), git push
操作之后两个分支同步了。
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is ahead of 'origin/dev' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
albert@homepc MINGW64 /d/gitstart (dev)
$ git log
commit a5b6c18db71a0487f6316f5db4304a99984f2ab3 (HEAD -> dev)
Author: albert <qianxuan101@163.com>
Date: Sat Mar 7 15:51:56 2020 +0800
modify readme 1
commit 3226b63185a16398a02d5eaea47c95309ba49588 (origin/master, origin/dev, release, master)
Author: albert <qianxuan101@163.com>
Date: Wed Feb 26 00:36:35 2020 +0800
add readme file
albert@homepc MINGW64 /d/gitstart (dev)
$ git push
Warning: Permanently added the ECDSA host key for IP address '180.97.125.228' to the list of known hosts.
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 286 bytes | 286.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-3.8]
To gitee.com:myname/gitstart.git
3226b63..a5b6c18 dev -> dev
这时通过远程仓库的管理软件,你可以看到远程分支已经有了最新的提交,然后我们可以参考 <还原04>
的情况,先将本地日志还原,再推送到远程仓库。
albert@homepc MINGW64 /d/gitstart (dev)
$ git reset HEAD^
Unstaged changes after reset:
M README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is behind 'origin/dev' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
albert@homepc MINGW64 /d/gitstart (dev)
$ git log
commit 3226b63185a16398a02d5eaea47c95309ba49588 (HEAD -> dev, origin/master, release, master)
Author: albert <qianxuan101@163.com>
Date: Wed Feb 26 00:36:35 2020 +0800
add readme file
albert@homepc MINGW64 /d/gitstart (dev)
$ git push
To gitee.com:myname/gitstart.git
! [rejected] dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@gitee.com:myname/gitstart.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
和想象的不太一样的,这种情况是远程仓库的记录领先,无法直接推送,此时可以添加 -f
参数,用本地提交记录覆盖远程分支记录:
albert@homepc MINGW64 /d/gitstart (dev)
$ git push -f
Total 0 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-3.8]
To gitee.com:myname/gitstart.git
+ a5b6c18...3226b63 dev -> dev (forced update)
这次再查询远程分支记录,发现也被回退了,目的达成。
git commit
之后产生两条日志,只还原第一次提交这种情况其实发生了两次修改和两次提交,和 <还原05>
情况不同的是要还原的提交不是最后一次,如果使用 git reset
命令必然将最后一次修改也还原了,虽然不能直接完成,但是给我们提供了解决问题的思路:
第一种方法:直接使用 git reset HEAD^^
命令还原两次提交,然后在工作区将文件按第二次修改再改一次进行提交,这种方法适用于想要抹除第一次提交历史的情况。
第二种方法:如果你不在意提交历史,只是想还原第一次修改,那么可以使用 git revert HEAD^
命令来反向修改那一次变化,修改之后会自动添加到暂存区,等待提交。
先来修改提交两次,产生两次记录:
albert@homepc MINGW64 /d/gitstart (dev)
$ git status
On branch dev
Your branch is up to date with 'origin/dev'.
nothing to commit, working tree clean
albert@homepc MINGW64 /d/gitstart (dev)
$ echo "m1">>README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git add README.md
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory
albert@homepc MINGW64 /d/gitstart (dev)
$ git commit -m"modify README 1"
[dev e570df1] modify README 1
1 file changed, 1 insertion(+)
albert@homepc MINGW64 /d/gitstart (dev)
$ echo "m2">>README.md
albert@homepc MINGW64 /d/gitstart (dev)
$ git add README.md
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory
albert@homepc MINGW64 /d/gitstart (dev)
$ git commit -m"modify README 2"
[dev 140547f] modify README 2
1 file changed, 1 insertion(+)
gi
albert@homepc MINGW64 /d/gitstart (dev)
$ git log
commit 140547f8d0b10d9a388beaf2ce522c38c878a839 (HEAD -> dev)
Author: albert <qianxuan101@163.com>
Date: Sat Mar 7 16:26:17 2020 +0800
modify README 2
commit e570df134b39ee7424bc8c48c1067e72c3fb9637
Author: albert <qianxuan101@163.com>
Date: Sat Mar 7 16:26:07 2020 +0800
modify README 1
commit 3226b63185a16398a02d5eaea47c95309ba49588 (origin/master, origin/dev, release, master)
Author: albert <qianxuan101@163.com>
Date: Wed Feb 26 00:36:35 2020 +0800
add readme file
albert@homepc MINGW64 /d/gitstart (dev)
$ cat README.md
learn git branch command
m1
m2
然后使用 git revert HEAD^
还原第一次修改记录:
albert@homepc MINGW64 /d/gitstart (dev)
$ git revert HEAD^
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
error: could not revert e570df1... modify README 1
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
albert@homepc MINGW64 /d/gitstart (dev|REVERTING)
$ vi README.md
albert@homepc MINGW64 /d/gitstart (dev|REVERTING)
$ git add README.md
albert@homepc MINGW64 /d/gitstart (dev|REVERTING)
$ git commit
[dev 6ae97d0] Revert "modify README 1"
1 file changed, 1 deletion(-)
albert@homepc MINGW64 /d/gitstart (dev)
$ git log
commit 6ae97d0e136abc1ed241854298037ca9d1c4460c (HEAD -> dev)
Author: albert <qianxuan101@163.com>
Date: Sat Mar 7 16:31:50 2020 +0800
Revert "modify README 1"
This reverts commit e570df134b39ee7424bc8c48c1067e72c3fb9637.
commit 140547f8d0b10d9a388beaf2ce522c38c878a839
Author: albert <qianxuan101@163.com>
Date: Sat Mar 7 16:26:17 2020 +0800
modify README 2
commit e570df134b39ee7424bc8c48c1067e72c3fb9637
Author: albert <qianxuan101@163.com>
Date: Sat Mar 7 16:26:07 2020 +0800
modify README 1
commit 3226b63185a16398a02d5eaea47c95309ba49588 (origin/master, origin/dev, release, master)
Author: albert <qianxuan101@163.com>
Date: Wed Feb 26 00:36:35 2020 +0800
add readme file
因为修改了同一个文件,还原的时候还产生了冲突,解决冲突之后才提交,看日志发现这是一条新的记录,在实际操作的过程中可能会发生比这还要麻烦的场景,多练就好了。
使用 Git
进行版本管理时,遇到的回退情况远不止这么多,这只是我目前常见的,之后遇到还会补充,每种情况我们其实不止有一种解决方式,接下来对于每种情况给一个我个人常用的处理方式,因为 git checkout
的作用被逐渐拆分成更具体的 git switch
和 git restore
,我们尽量选择功能明确的命令:
git add
操作git restore --staged file_name
命令,如果版本不支持则使用 git rm --cached file_name
git add
操作git restore file_name
命令,如果版本不支持则使用 git checkout -- file_name
git add
操作git restore --staged file_name
命令,按 <还原02>
情况处理git add
、git commit
操作git reset HEAD^
命令,按 <还原02>
情况处理,或者使用 git reset --soft HEAD^
命令,按 <还原03>
情况处理git add
、git commit
、git push
操作<还原04>
情况处理,然后使用 git push -f
命令git commit
之后产生两条日志,只还原第一次提交git revert HEAD^
命令,解决冲突后提交,revert 后面跟具体的 commit id
也可以。git status
之后都有列举git status
是一个可以提示你做选择的强大帮手,不知所措时可以试试它git switch
和 git restore
命令,因为之前 git checkout
背负了太多了