Git使用(4)修改提交结果、版本回退与冲突解决

时间:2022-09-06 15:07:14

1.查看版本之间差异

1.1查看有哪些文件夹/文件有差异

git diff
显示工作目录与暂存区文件之间的差异
git diff --cached
显示暂存区与git仓库之间的差异
git diff HEAD
显示工作目录与git仓库之间的差异
(以上三种都是现在跟前面相比较)

git diff HEAD – ./test
比较当前分支上,工作区与HEAD 在test文件的变化(常用,注意中间是两横)
git diff – HEAD ./dir
比较当前分支上,工作区与HEAD 在dir文件夹下变化(常用)
git diff – ./test比较工作区和暂存区之间的变化
git diff test_branch
比较test_branch 分支而非当前分支,比较内容同上
git diff commit1 commit2:如
git diff HEAD^ HEAD
比较HEAD的前一个版本和HEAD
1.2 查看某文件的修改记录:
git log -p ./dir/file1.txt
会打印出所有修改记录及其版本HASH值。接下来可以通过版本回退找到该文件中那个版本的内容(参见2.2)

2.修改commit信息

2.1 修改本地 commit信息

加入commit 提交了,但又发现注释写得不够完善,想再次修改,怎么办?
可以使用:

git commit -- amend

随后就像操作vim一样进行操作,修改完毕,:q,保存即可。
还有一种方法,是下边介绍的:

git reset --soft  HEAD^ 

修改后再重新提交即可。

2.2修改远程commit信息

加入不小心提交到远程仓库,但发现commit写得有问题,怎么办?
方法1:
回退本地版本,再强制同步远程版本,使之与本地同步:

git reset --hard HEAD^
git push -f origin localRepo:remoteRepo

3.版本回退与历史修改

3.1本地整个版本回退

方法1:git reset
知道版本号(就是那个hash值)后,就可以
git reset了,它有三个参数:
git reset –mixed //默认,回退版本库历史(即移动HEAD指针),工作区不变,暂存区(index)清空(有的地方说缓存区reset,有的地方使缓存区和当前HEAD内容一样,但两种说法实质是一样的,因为缓存区是用来记录与当前working directory相比变化的内容(./git/index是一个二进制文件,包含已排好序的文件名、文件索引、文件元数据等,这些数据一起构成当前的缓存),所谓当前index与working directory一致,就相当于index清零)
git reset –soft //回退版本库历史到某一版本,工作区不变,暂存区(index)不变。
git reset –hard//回退版本库、工作区到某一版本,清空暂存区(危险,一般应在此操作前git status 确认无重要更改)
其差别可用此图解释:
Git使用(4)修改提交结果、版本回退与冲突解决
git reset –hard d25062cd5

不论是hard还是soft,现在比d25062cd5更新的几个提交都变成了悬挂提交。下次Git执行垃圾回收的时候,这几个提交会被删除。

常用的还有:git reset HEAD //清空缓存区,回退到最近一次提交的版本。

如果后悔了想回退到之前的版本,但此处找不到最新那个版本的id了,怎么办?可以通过:
git reflog
git reflog可以记录自己的所有操作,包括所有HAED的变动情况,以及对应的HEAD的hash值。

ea34578 HEAD@{0}: reset: moving to HEAD^
3628164 HEAD@{1}: commit: append
ea34578 HEAD@{2}: commit: add distributed
cb926e7 HEAD@{3}: commit (initial): wrote a readme file

发现最后一次提交,即最新版本是3628164。随后可以git reset –HARD 到之前那个HEAD哈希值所在版本。
除此之外
如果原来版本中有文件没有被提交到版本库里,这样版本之间切换后找不到原来的了。只要之前将该文件git add到缓存区了,也可通

git fsck --lost-found

然后就能在.git/lost-found下找到找到缓存文件
方法2: git revert撤销上一次提交
git revert 和git reset的差别是,git revert是代码回退到原来版本,但不会删除提交历史,同时会产生新的提交id,而git reset是回退代码,同时删除了提交历史。
git revert 语法与git reset差不多

git revert HEAD
git revert commit_id

随后会出现编辑框,可以编辑自己的一些commit信息。
revert 是撤销一次提交,commit_id代表的版本被撤销,所以最终是回滚到commit id的前一次提交。

如果使用 revert 撤销的不是最近一次提交,那么一定会有代码冲突,需要你合并代码,合并代码只需要把当前的代码全部去掉,保留之前版本的代码就可以。所以一般使用git reset来回滚到比较远的版本,以免大量的代码冲突。
方法3:

3.2本地部分文件回退

接1.2:恢复某文件/文件夹的内容到某版本
git checkout – ./dir 恢复到上一个版本

一种是该目录下自修改后还没有被放到暂存区(即没执行过git add),现在,撤销修改就回到和版本库一模一样的状态;
一种是该目录已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
所以如果强制要会退到版本库历史中保存的最新版本,建议:git checkout HEAD –./dir

git checkout d25062cd5 – ./file.txt //恢复到某一指定版本

git checkout //恢复版本到上一版本
git checkout d25062cd5 //恢复版本到某历史版本

3.3远程仓库版本回退

假如不小心有错误的提交,则可以使用以下方式:
如果是私有开发分支,或者不想留下撤销的记录,则可以:
git push -f
直接将本地版本回退,然后git push -f,覆盖远程分支。好用无风险。
更暴力方法
或者:直接从那个错误的提交的前一次拉取一份代码放到其他目录,然后将master代码全部删除,把那份新代码方进去,然后提交。
对于公共开发分支,考虑到可能在我提交后有人已经pull,所以需要保留所有版本记录:则只能借助于:
1) git revert HEAD

3.4删除某次较远的提交记录

git log//查找对应的记录id
git rebase -i commit_id//会跳出一个编辑框,需要在编辑框中将版本号对应的一行删除。
git push -f

附录:

HEAD, HEAD^, HEAD^^, HEAD~3,HEAD~100:当前版本库最新历史版本,上一个版本,上上个,上上上(第3)个,倒数第100个

参考:

1.git文件夹详解