git 后悔药

git 后悔药

前言

lilac 按:

错事常常有,后悔药却难寻。你是不是经常因为做错事而搜寻不到后悔药而苦恼万分呢?生活中很多事情确实无后悔药可吃,可是在git的世界里,只要用心思考,还是能找到不少好用的后悔药的。

如下几副后悔药为lilac思考总结的成果,如有不当,还请大佬们留言探讨,lilac先行谢过~

gitrepo-1.jpeg
  • Workspace:工作区
  • Index / Stage:暂存区
  • Repository:仓库区(或本地仓库)
  • Remote:远程仓库

git 中存在工作区,暂存区,本地仓库和远程仓库几个概念,上图比较直观地说明了这几个区之间的操作(图片来源于网络)。平时通过git进行代码管理时,一般也是将改动在这几个区之间进行变换。

P.S. 划重点啦!!!

在 Git 中任何 已提交的 东西几乎总是可以恢复的,甚至那些被删除的分支中的提交或使用 --amend 选项覆盖的提交或使用reset --hard命令重置后的提交等都是可以恢复的。 然而,任何你未提交的东西丢失后很可能再也找不到了。

因此在使用git时,比较保险的做法是多采用commit命令提交代码,即便你有代码洁癖,想维持提交记录的清晰可读性,也可以多次提交,反正有办法可以从历史提交记录中去掉某个指定的提交,也可以将多个提交合并为一个提交。

接下来分情况讨论下git的各种后悔药吧,下文的分析脉络如下面的脑图所示。

备注:所有没有被git托管的文件如果没有自己手动进行备份的话,是不存在后悔药的,故不做讨论。

Git后悔药.png

约定: 后文中英文方括号[]中的内容表示可选内容,当可选内容为commitID时,若不填,则表示采用HEAD所指向的提交。

示例

下面通过一个具体的实例演示各种后悔药的服用方法。

入职几天后,Jack 对组内工作已略微熟悉,找 mentor 接手了一个小任务,想要好好表现一番。

他首先加入了项目组的中央仓库,并拉取了组内前辈们的代码,然后便开始了边听歌,边写代码实现功能的节奏。

情况一 撤销工作区的修改

写到一半,突然想到有个文件的代码修改考虑不周,需要推翻重写。可是这份代码是在已有文件上进行修改的,不能删除重来,并且修改量还挺大的,一行一行修改回来的话,实在是有点傻。Jack 开始烦恼了。。。

此时可以服用第一方后悔药:撤销工作区的修改

在某个 git 仓库中,修改了文件 file 后,发现此次修改不对,想要放弃此次修改,或者想要将 file 恢复到某个指定的状态,此时可以用 git checkout 命令

git checkout [commitID] [file1][file2]...

如:
git checkout file1          # 将文件 file1 恢复到 HEAD 所指向的提交的状态,即上一次提交的时候的状态
git checkout commit file1       # 将文件 file1 恢复到 commitID 所指向的提交的状态

采用 git checkout 命令将吴修改的文件恢复到修改前的状态后,Jack 又可以愉快地开始写代码了。。。

情况二 撤销暂存区的修改

写着写着,午饭时间到了,同事们叫 Jack 一起去吃午饭。Jack 心想着,还是先提交一下,备份下代码吧,万一吃完饭回来,手欠将好不容易写好的代码给弄没了呢。于是 git add . 了一下,哈哈,这个命令可还是不要随便用的好呀,这不,一不小心就把不该提交的修改内容添加到暂存区了吧。

第二方后悔药:撤销提交到暂存区的修改

git reset [commitID] [file1] [file2]...
​
如:
git reset commitID       # 将暂存区和本地仓库的内容重置为 commitID 所指向的提交
git reset file1 file2    # 撤销 file1 file2 的 add 操作</pre>

情况三 撤销已提交到本地仓库的修改

撤销完本不应该添加到暂存区的文件后,Jack 运行 git commit 命令完成了第一次提交,终于可以安心地去吃午饭了。饭后,Jack 又完成了几次提交,在某一次提交后,发现有几次提交的内容不太恰当,想要撤销这几次提交,重新提交。

第三方后悔药:撤销已提交到本地仓库的修改

若此次提交还未 push 到远程仓库,那么可以调用 git reset 命令重置 HEAD 指针,或调用 git revert 命令撤销此次提交的修改。若此次提交已经 push 到远程仓库,那么只能调用 git revert 命令撤销此次修改,然后重新提交正确的内容,并 push 到远程仓库。此时如果调用 git reset 命令重置 HEAD 指针的话,会导致本地 HEAD 指针落后于远程仓库的 HEAD 指针,从而在 push 时出错。

git reset [commitID]
git revert commitID

如:
git reset commitID    # 重置 HEAD 指针,使其指向 commitID 对应的提交
git reset HEAD^       # 重置 HEAD 指针,使其指向 HEAD 的父提交
git revert commitID   # 创建一个新的提交,其内容为撤销 commitID 对应的修改
git revert HEAD       # 创建一个新的提交,其内容为撤销 HEAD 指向的提交对应的修改

情况四 撤销已提交到远程仓库的修改

一般来说,不能撤销已经提交到远程仓库的修改,尤其是那些已经提交到一个与他人合作的分支的修改。但是,可以通过 git revert 命令创建一个新的提交,撤销上一个提交的修改,然后重新 push 到远程仓库来变相完成撤销已提交到远程仓库的修改。

P.S. 如果想要撤销的提交位于一个自己独有的远程分支上的话,也可以采用硬重置远程分支的方式来强制撤销已提交到远程仓库的修改。不过此类操作有风险,需谨慎执行。

示例:

假设远程分支 A 是一个 Jack 独有的分支,此时 Jack 想要撤销分支 A 上的一个提交,那么他可以按照如下操作

git checkout HEAD^ -b AR  # 创建本地分支 AR,指向本次提交的上一次提交,也就撤销了本次提交的修改
git log --oneline --all   # 查看所有分支的日志,每次提交一行,以确保 AR 指向的提交符合自己想要的状态
git push origin :A        # 如果 AR 指向的提交满足自己的需求,那么可以通过该命令删除远程分支 A
git push origin AR:A      # 将本地分支 AR 指向的提交提交到远程分支 A

至此,便真正撤销了已提交到远程仓库的修改</pre>

扩展知识

git checkout 命令详解

git checkout 命令有两项功能:

  • 切换到指定分支;

  • 将工作区的文件恢复到指定提交对应的状态;

使用语法:
git checkout [-q] [-f] [-m] [<branch>]
git checkout [-q] [-f] [-m] --detach [<branch>]
git checkout [-q] [-f] [-m] [--detach] <commit>
git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>]
git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
git checkout [<tree-ish>] [--] <pathspec>...
git checkout (-p|--patch) [<tree-ish>] [--] [<paths>...]</pre>

如果给定 checkout 命令的路径,那么会恢复路径指定的文件到指定提交的状态;如果指定分支名,则切换到指定分支;如果给定 -b 选项,那么会新建一个名为<new_branch>的新分支,并切换到该分支。

示例:
git checkout br        # 切换到 br 分支
git checkout -b br1    # 创建新分支 br1,并切换到 br1 分支
git checkout file      # 将工作区中的文件 file 恢复到上一个提交对应的状态,即撤销工作区对 file 的修改
git checkout -- file  # 与上一条命令含义相同,添加 -- 是为了避免文件名和分支名一致而引发歧义
git checkout <commit> --file  # 将工作区中的文件 file 恢复到 commit 提交对应的状态

git reset 命令详解

git reset 命令用于将 HEAD 指针重新指向某一个指定的提交,并根据 选项参数 而决定是否修改暂存区和工作区中的内容以与 HEAD 指针指向的内容相匹配。当给 reset 命令指定作用路径时,表示将路径指向的文件恢复到 add 操作前的状态,即与 git add 操作是一个相反的过程。

使用语法:
git reset [-q] [<tree-ish>] [--] <paths>...
git reset (--patch | -p) [<tree-ish>] [--] [<paths>...]
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
示例:
git reset --soft <commit>     # 只改变HEAD指针,暂存区和工作目录的内容保持不变
git reset --mixed <commit>    # 改变HEAD指针,同时改变暂存区的内容,工作目录的内容保持不变
git reset --hard <commit>     # 暂存区、工作区的内容都会被修改到与HEAD指针完全一致的状态
git reset --hard HEAD         # 让工作区回到上次提交时的状态
git reset file                # 将文件 file 恢复到 add 前的状态</pre>

《Git Pro》一书中将 git reset 命令和 git checkout 命令通过图示的方式解释得非常清楚,建议大家阅读一下。

git reset VS git revert

  • git revert 是用一次新的 commit 来回滚之前的 commit,git reset 是直接删除指定的 commit;

  • 虽然从回滚的结果来看,这两者差不多,都能使 commit 指向的内容恢复到修改前的状态,但这两者的作用过程是不同的。git revert 会新增一次 commit 来撤销指定 commit 的修改,而被撤销的提交依然是存在的,所以在与包含该被撤销的提交的分支进行 merge 时不会出现冲突,而 git reset 是直接删除需要被撤销的 commit,导致该 commit 在该分支上不复存在,从而在与包含该被撤销的提交的分支进行 merge 时,会存在冲突;

  • git reset 是把 HEAD 指针向后移动了一下,而 git revert 是将 HEAD 指针继续向前移动了一步,只是新的commit 的内容和要 revert 的 commit 的内容正好相反,能够抵消要被 revert 的 commit 的修改。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容