案例:现在的微服务都有自动生成工具generater
,首先通过生成器生成了一些代码,这里成为A版本,在A版本的代码中,修改了部分代码,并git push到远程仓库。这时由于变动,需要追加内容,于是重写了配置文件,再次使用生成工具生成了版本B。单纯生成代码A是B的真子集,但是A改动过,改动过的部分成为a,此时就出现了问题,新生成的版本B中a被覆盖,没有了,使用git pull命令也拉不下来,这个情况该如何解决呢?
如下图所示,就是上述情况:
本地工作区
B版本生成的被覆盖,缺少a部分也就是,A中修改或追加的部分
远程仓库的文件如下,这些都是存在的
这种情况可能会想到复制粘贴解决,将缺失的从线上复制下载粘贴到本地,再重新提交。这种方式只适用于少部分代码,如果代码量很多,工作量就特别大。
分析:
- 问题原因?
为什么git pull无法将缺失的代码拉下来?
首先远程仓库必定和本地仓库的某个版本完全一致,此时重新生成的B把修改的部分顶掉了,生成了新的文件,这时git已经检测到文件变动了,但是开发者仍然使用git add,git commit
(git add可能由ide自动完成),如下
开发者会把重新生成的覆盖修改了的文件再次
git commit
最后代码就丢了,如下图,在历史提交版本都还能看到
此时千万别git push因为一传到远程仓库就就把远程仓库也顶掉了。
下面介绍三种修复办法:
- ide的git工具
使用
Revert Commit
或者Undo Commit
或者Drop Commit
这些命令比较好理解,自行查阅资料。这些命令只适用于未push的阶段。撤回之后将被顶掉的文件不勾选再次commit就可以了。
- git revert和git reset
git reset命令用户在commit的追踪树之间任意穿梭,可以切换到任意几点的commit记录。git reset将文件移除缓存区就是通过移动该文件的追踪记录,到未git add 的节点。
在使用git reset命令时,需要指定要回滚到的版本号或者提交点。常用的参数有--soft
、--mixed
和--hard
。其中,–soft参数表示只回滚提交的信息,保留修改的文件;–mixed参数表示回滚提交的信息和修改的文件,但是不保留修改的内容;–hard参数表示彻底回滚到指定的版本,包括提交的信息和修改的文件,同时丢弃修改的内容。
git reset是将代码库回滚到指定的版本,丢弃之后的修改内容,而git revert是创建一个新的提交,撤销之前的提交内容。git reset是在本地仓库中进行操作,不会影响到远程仓库,而git revert会创建一个新的提交,需要将其推送到远程仓库。
在git追踪记录找到未顶掉的版本号里这里只需要找到该文件修改文件节点就可以了。
通过git log命令找到未提交的版本记录,然后git reset [版本] [filename]
即可,commit id
可以通过git log
查看。
git revert
和git reset具有相似的功能,但是git revert是创建一个新的commit而这个版本和需要恢复的版本一样。
git reset只能在当前版本使用,但是git revert可以直接对历史版本使用。
在历史节点使用git revert更快,如下图:
- git rebase或者git merge
使用这两种办法,需要从远程仓库重新来拉分支,但要确保没有push,拉来分支后,使用git merge
或者git rebase
融合分支,使代码融合就行了。