Git 逆转时光:版本回退操纵详解

打印 上一主题 下一主题

主题 1847|帖子 1847|积分 5551

一、Git的工作流程

在讲这个版本回退之前,我们要温习一下Git的原理。下面这张图就是 Git 的整个工作流程,也是 Git 抽象出来的几个概念。

Git 的四个地区:


  • workspace:当地工作区,就是你平时存放项目代码的地方。比如你拉取代码git clone ssh://fly@192.168.31.91:/home/fly/srcs,srcs目录就是当地工作区了。开辟者就在工作区里写代码。
  • Index / Stage:暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息。值得一提的是,SVN 是没有暂存区概念的。暂存区允许把多次修改统一放在暂存区中,然后再由暂存区统一提交到当地仓库,确保提交记录清晰。
  • Repository: 当地仓库区(或版本库),就是安全存放数据的位置,这里面有你提交到全部版本的数据。其中HEAD指向最新放入仓库的版本。
  • Remote: 远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换。
Git 的 工作流程 一样平常是这样的:


  • 在工作区目录中添加、修改文件;产生数据变更。
  • 将需要进行版本管理的文件add到暂存地区;
  • 将暂存地区的文件commit到git仓库;
  • 当地的修改push到远程仓库,如果失败则执行第5步;
  • git pull将远程仓库的修改拉取到当地,如果有辩说需要修改辩说,回到第三步。
因此,git管理的文件至少有三种状态:已修改(modified)、已暂存(staged)、已提交(committed)。
二、git clean尚未 commit 的修改

当地做了一些修改,包罗修改了某些文件,增长了某些文件,删除了一些目录,也添加了一些目录,有些内容添加到了暂存区,有些没有。情况很复杂,但是、总之,这些修改没有commit到当地仓库,那此时我们说的版本回退就是指抛弃修改。那如何操纵呢?

从原理图中,看到git checkout命令就是从当地仓库中或暂存区检出文件,而且覆盖工作目录的内容。比如:
  1. # 检出到branches/stable-1.14分支上,即用1.14分支的内容覆盖了工作区所有内容
  2. git checkout branches/stable-1.14  
  3. # 检出到9bfbacdd(commit id)上,即用这个commit 内容覆盖了工作区所有内容
  4. git checkout 9bfbacdd  
  5. # 从暂存区中检出内容,并且覆盖main.cpp文件内容,即尚未添加到暂存区的修改会被丢弃掉
  6. git checkout main.cpp
复制代码
但是上面都是说从git的当地仓库和暂存区里检出内容,然后覆盖掉工作区的内容,即抛弃了当地全部的修改。
那如果是有些内容已经存在工作区了,但是尚未提交到暂存区,便是untracked的内容,那么我们可以使用git clean命令来删除这些文件,用法如下:


  • git clean -n :是一次clean的演习,告诉你哪些文件会被删除,记住他不会真正的删除文件,只是一个提醒。
  • git clean -f :删除当前目录下全部没有track过的文件,他不会删除.gitignore文件里面指定的文件夹和文件,不管这些文件有没有被track过。
  • git clean -f <path> :删除指定路径下的没有被track过的文件。
  • git clean -df :删除当前目录下没有被track过的文件和文件夹
  • git clean -xf :删除当前目录下全部没有track过的文件,不管他是否是.gitignore文件里面指定的文件夹和文件。
好了,如果我们想要放弃当地的全部修改可以:


  • git checkout .:注意有一个“.”,会从暂存区里取出全部内容覆盖掉工作区的全部修改,如果连暂存区的内容也不想要则可以git checkout commit-id。
  • git clean -xdf:删除当前目录下全部的修改。
如果我们想要放弃当地某个文件的修改:
  1. git checkout file-name  # 从暂存区里
复制代码
三、已经 commit 尚未 push 到 remote 仓库

有时候,我们在当地的修改,可能提交到了当地仓库,但是尚未push到远程仓库,针对这一种场景的
回滚是比力简单的,如下图所示:

origin/master指向了5ff5433b这个commit,当地有三个commit,现在想针对这三个commit作回滚,可
以使用git reset命令来做,reset参数如下:


  • --soft:缓存区和工作目录都不会被改变
  • --mixed:默认选项。你指定的提交同步,但工作目录不受影响
  • --hard:缓存区和工作目录缓存区和都同步到你指定的提交
git reset --hard HEAD~{n}就是把HEAD指针回退n个版本(commit),而且使用该commit的内容覆盖掉工作区的内容,即抛弃了前面n个commit的修改和当前工作区的修改。然后调用git push origin master推送到远程仓库。
四、已经提交到 remote 仓库

在使用Git进行版本控制时,如果我们已经将当地的代码提交(push)到了远程仓库,那么我们需要考虑两种情况。
起首,我们需要判断我们提交的代码是否有其他同事已经在此根本上进行了修改,而且将这些修改也推送到远程仓库。如果其他同事已经在我们的提交之上进行了修改,而且这些修改已经被推送,那么如果我们直接回退(比方使用 git reset),将会导致这些同事的修改被抛弃。同时,这种操纵还会删除历史记录,这可能不符合我们的预期,尤其是在团队协作中,这会对同事的工作造成影响。
另一方面,如果没有其他同事在我们的提交上进行修改,那么我们可以考虑使用 git revert 来回退我们的提交。这种方法会创建一个新的提交,以抵消我们想要回退的那个提交,这样既保存了历史记录,也不会影响到其他同事的工作。
有些人可能会问,为什么不使用 git reset 呢?由于 git reset 会完全删除关于指定提交的历史记录,这样不仅会导致记录的不完备,也会对团队中的其他成员产生负面影响。因此,使用 git revert 是更好的选择。
具体来说,假设我们当前有三个提交,如果我们盼望回退到某个特定的提交(比如 d061cb3),而这个提交之后的工作并不是我们想要的,那么我们应当使用 git revert d061cb3 来进行回退操纵。这样做可以确保我们的操纵是安全的,而且符合团队协作的最佳实践。
示例:
  1. git revert d061cb3 # 因为4bff67b是晚于d061cb3的,如果这两个修改的内容有依赖,是会有冲突的,
  2.                    # 当然如果想取消这次回退可以使用,git revert --abort
  3. fix conflict  # 手动去解决冲突
  4. git commit  # 然后提交,此时使用git log会发现原理的git commit记录还在,
  5.             # 但是增加了一个revert的记录
  6. git push    # 推送至远程库
复制代码
如果有别的同事基于我们的commit做修改的话,我们回退版本的时候不想把他的提交给回退
掉,比如想回滚到5ff5433b这里,但是有其他人的一个提交我不能回滚掉,要保存他的代码,
而且如果有多个同事的修改在在5ff5433b之后的,那怎么办呢?
比力好的做法就是从5ff5433b拉取一个新的分支(分支名是reset_to_5ff5433b), 由于这个新分
支不包罗要回滚的代码,此时我们可以把别的同事的修改手动归并到reset_to_5ff5433b分支,接着
切换到master分支上,使用git merge reset_to_5ff5433b去归并分支到master上。这也就是分支操纵的知识点。
  1. # 从5ff5433bd1fe4处创建分支,即代码是5ff5433bd1fe4处的代码
  2. $ git checkout -b reset_to_5ff5433b 5ff5433bd1fe4
  3. # 查看master分支上的其它同事的提交(比如KING),把他的修改在新分支上再修改一遍
  4. $ git show 9d531db98276
  5. $ git commit –a –m "reverted 5ff5433b"
  6. # 切换到master分支
  7. $ git checkout master
  8. $ git merge reset_to_5ff5433b
  9. $ git push #推送到远程仓库
复制代码
五、回退建议

在日常开辟中,频繁回退(纵然用 git revert 或 git reset)可能会影响工作服从和代码的整洁性。应当制止频繁回退:

  • 定期提交:将工作分解成小的、可管理的任务,并在完成每个小任务后提交。这使得每个提交都比力小,回退时不会影响太多代码。
  • 写清晰的提交信息:确保每次提交的信息清楚明了,阐明你做了什么以及为什么做。这样在需要回退时,可以更容易地明白代码更改的历史。
  • 使用分支:在开辟新特性或者进行大改动时,使用分支(比方 feature 分支)进行开辟。这样可以在主分支上保持稳固,开辟完成后再归并。
  • 代码检察:在归并代码之前,进行代码检察,确保代码的质量以及逻辑的正确性。这样可以减少因错误而导致的回退。
  • 测试:在提交之进步行测试,确保全部功能正常。这可以大大减少后续回退的可能性。
  • 利用暂存区:使用 git add -p 选择性地添加更改到暂存区,这样可以更好地控制哪些更改会被提交,从而制止不须要的错误提交。
  • 分阶段开辟:如果某个特性较复杂,可以将其分成几个阶段来开辟。每完成一个阶段,就进行一次提交,可以减少大规模的回退。
  • 使用标签:在紧张的版本发布前打标签(git tag),这样在回退时可以更方便地找到之前的稳固版。
六、总结

在使用Git时,可能会遇到需要回退的情况。明白和掌握Git的回退操纵,对于高效地管理代码至关紧张。
Git版本回退的主要方法:


  • git revert:用于打消一个提交的更改,创建一个新的提交来逆转之前的更改。这是一种安全的回退方法,由于它保存了历史记录,不会影响到其他团队成员的工作。
  • git reset:用于重置当前分支到指定的提交,可以删除之后的提交记录。虽然它可以更彻底地回退更改,但它会修改提交历史,因此在公共分支上使用时需要小心。
  • 要制止频繁回退。
掌握Git不仅仅是相识其根本命令,更是通过实践来真正明白其工作原理和最佳使用方法。通过不断的实践和学习,将可以或许更好地掌握Git的使用,提高代码管理的能力和开辟服从。Git是一个工具,而醒目它的使用将使你成为一个更优秀的开辟者。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

篮之新喜

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表