Git 时间线管理

Git 时间线管理

这一部分主要讲的是 取消(undo) 变化 和在不同的时间锚点跳来跳去,以 command 为主。

设计到的commits有:

  • checkout
  • restore
  • reset
  • revert

checkout

checkout 的一部分作用,即切换分枝在 git 分支操作 中有提到过,不过 checkout 本身的用途更多。有些开发甚至觉得 checkout 的功能太多了,最终将功能分割之后生成了新的 switchrestore

除了分支管理之外,checkout 还能用来还原文件和 undo history。

checkout commit

下面会 checkout 一个 commit hash:

# 可以完整cv整个hash,或者截取前 7 位作为hash key
➜  basic git:(main)git checkout f8b2e15
Note: switching to 'f8b2e15'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at f8b2e15 start work on outline and characters
➜  basic git:(f8b2e15)git status
HEAD detached at f8b2e15
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        git.md

nothing added to commit but untracked files present (use "git add" to track)

现在解释一下 detached HEAD 是什么意思,正常情况下,当前 branch 指向当前 commit,而当前 head 指向当前 branch,也就可以理解成是当前 commit 的 reference,这个时候的 head 是当前 commit 的 symlink:

HEAD
branch
commit2
commit

软件上看起来是这样的:

在这里插入图片描述

但是当直接 checkout 到一个 commit 之后,当前的分支依旧之乡最后一个 commit,HEAD 则是只想当前的 commit:

HEAD
commit
branch
commit2

也就是说 HEAD 从 branch 上分离(detach)了,软件上看起来是这样的:

在这里插入图片描述

这时候的 HEAD 直接作为当前 commit 的 reference。

checkout commit 的用途有

  1. 查看原始文件

    大多是时候发生在某个版本不工作了,然后要要 revert 到某一个版本

  2. 创建一个新的分支

    就像 switch 到一个新的分支会创建一个新的历史一样,checkout 到某一个 commit 也会创建一个新的历史分支

    ➜  basic git:(main)git checkout f8b2e15
    ➜  basic git:(f8b2e15)git switch -c new-ch2
    Switched to a new branch 'new-ch2'
    ➜  basic git:(new-ch2)git commit -m "create new version of ch2"
    [new-ch2 12da43a] create new version of ch2
    1 file changed, 1 insertion(+)
    create mode 100644 ch2.txt
    ➜  basic git:(new-ch2)

    此时的分支看起来如下:

    在这里插入图片描述

    此时的 HEAD 不是一个 detached 状态,而是重新绑定到了新创建的 new-ch2 分支上。而该分支没有保存的变化,依旧保存在另一个分支上。

如果没有做任何的变动,想要切换到原有的分支,可以直接使用 git checkout branchname 执行。

git checkout HEAD~

具体语法为:git checkout HEAD~1,其中 HEAD~ 后跟数字,如果是 1 就惠滚到上一个 commit,以此类推。

图解如下:

在这里插入图片描述

顺便上面的 mermaid 语法为:

gitGraph
  commit id: "HEAD~5"
  commit id: "HEAD~4"
  commit id: "HEAD~3"
  commit id: "HEAD~2"
  commit id: "HEAD~1"
  commit type: HIGHLIGHT

运行如下:

➜  basic git:(new-ch2)git checkout main
Switched to branch 'main'
➜  basic git:(main)git checkout HEAD~2
Note: switching to 'HEAD~2'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at b18e966 update chapter 1

在这里插入图片描述

这个时候返回有两个方法:

  1. 记住原本分支

  2. 使用 git switch -,该指令会切换到上一个所在的分支,如:

    ➜  basic git:(b18e966)git switch -
    Previous HEAD position was b18e966 update chapter 1
    Switched to branch 'main'
    

git checkout HEAD

该指令可以用于重制已经修改的文件,这里会用一个新的 repo 做例子,初步设置如下:

➜  undo git:(main)touch cat.txt dog.txt
➜  undo git:(main)echo "first commit" > cat.txt
➜  undo git:(main)echo "first commit" > dog.txt
➜  undo git:(main)git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        cat.txt
        dog.txt

nothing added to commit but untracked files present (use "git add" to track)
➜  undo git:(main)git add .
➜  undo git:(main)git commit -m "first commits"
[main (root-commit) 6c98eb0] first commits
 2 files changed, 2 insertions(+)
 create mode 100644 cat.txt
 create mode 100644 dog.txt
➜  undo git:(main) cat cat.txt
first commit
➜  undo git:(main)echo 'second commit' >> cat.txt
➜  undo git:(main)echo 'second commit' >> dog.txt
➜  undo git:(main)cat cat.txt
first commit
second commit
➜  undo git:(main)git add .
➜  undo git:(main)git commit -m "second commit"
[main 5a999a7] second commit
 2 files changed, 2 insertions(+)

# 重复若干次

准备完了之后就可以用 git checkout HEAD <file>,缩写为 git checkout -- <filename> 去重制操作了,如:

➜  undo git:(main) git status
On branch main
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:   cat.txt
        modified:   git.md

no changes added to commit (use "git add" and/or "git commit -a")
➜  undo git:(main)git checkout HEAD cat.txt
Updated 1 path from 4899106
➜  undo git:(main)git status
On branch main
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:   git.md

no changes added to commit (use "git add" and/or "git commit -a")

➜  undo git:(main)git status
On branch main
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:   cat.txt
        modified:   dog.txt
        modified:   git.md

no changes added to commit (use "git add" and/or "git commit -a")
➜  undo git:(main)git checkout -- *.txt
➜  undo git:(main)git status
On branch main
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:   git.md

no changes added to commit (use "git add" and/or "git commit -a")

这个的使用场景可能在:

  1. 你真的搞砸了很多

  2. 重制 db 文件

    比如说我们的项目就是从 csv 中读取 db 文件的,然后每天都必须要更新 csv 中的 ref date,这个时候更新分支就会因为 csv 不 match 导致 conflict。

restore

像上文提到的,restore 是一个比较新的命令,用于重置一些 checkout 的功能。

git restore

该指令可以用于重制已经修改的文件,对标 git checkout HEAD <file>

➜  undo git:(main)git status
On branch main
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:   dog.txt
        modified:   git.md

no changes added to commit (use "git add" and/or "git commit -a")
➜  undo git:(main)git restore dog.txt
➜  undo git:(main)git status
On branch main
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:   git.md

no changes added to commit (use "git add" and/or "git commit -a")
➜  undo git:(main)

restore --source

另一个 flag 可以用来将当前文件还原到几个 commit 之前,语法为:git restore --source <HEAD~1|hashedvalue> <filename>,还愿的方法使用上一条指令即可。

例:

➜  undo git:(main)cat dog.txt
first commit
second commit
third commit
➜  undo git:(main)git restore --source HEAD~2 dog.txt
➜  undo git:(main)cat dog.txt
first commit
➜  undo git:(main)git restore dog.txt
➜  undo git:(main)cat dog.txt
first commit
second commit
third commit

restore --staged

具体指令:git restore --staged <file>,这条指令可以将已经 staged 文件拉出来,如:

➜  undo git:(main)touch wrongfile.txt
➜  undo git:(main)git status
On branch main
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:   git.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        wrongfile.txt

no changes added to commit (use "git add" and/or "git commit -a")
➜  undo git:(main)git add .
➜  undo git:(main)git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   git.md
        new file:   wrongfile.txt

➜  undo git:(main)git restore --staged wrongfile.txt
➜  undo git:(main)git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   git.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        wrongfile.txt

顺便,如果直接用 git status,git 会提示可以用什么指令进行操作,如 git restore --staged <file>...git add <file>...git restore <file>..

reset

git reset 用于重置 commits,我主要用来将几个 commits squash 到一个 commits 里面去,使用 git rest 会保留当前的变化。

案例:

➜  undo git:(main) git log --oneline
da7603f (HEAD -> main) mistake commit2
a34f0c8 mistake commit
50840de third commit
5a999a7 second commit
6c98eb0 first commits
(END)

➜  undo git:(main) git reset 50840de
Unstaged changes after reset:
M       cat.txt
M       dog.txt
M       git.md
➜  undo git:(main)git status
On branch main
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:   cat.txt
        modified:   dog.txt
        modified:   git.md

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        wrongfile.txt

no changes added to commit (use "git add" and/or "git commit -a")
➜  undo git:(main)git log --oneline
50840de (HEAD -> main) third commit
5a999a7 second commit
6c98eb0 first commits
(END)

可以看到,本来的变化没有丢还在这里。

对于 git 来说,它会重新将 HEAD 指向提供的 commit hash 值,并且将中间的变化保存在 working directory 中。

我常用的做法就是清理分支上的 commits(尽量保证一个修 bug 的 MR/PR 一个 commits,功能性的保证有理由的 staging,一般来说小功能在 3 个以下,大功能 5 个一下这样),或者是将当前的变化带到其他的分支上。当然,后者用 git stash 也可以。

如果想要将当前的变化和修改的文件全都删除,可以加上 --hard 这个 flag,其语法为 git reset --hard <commit>,如:

➜  undo git:(main) git add .
➜  undo git:(main)git commit -m "mistake commit"
[main fa07782] mistake commit
 2 files changed, 2 insertions(+)
➜  undo git:(main) git log --oneline
fa07782 (HEAD -> main) mistake commit
0608200 fourth commit
50840de third commit
5a999a7 second commit
6c98eb0
➜  undo git:(main)git reset --hard HEAD~1
HEAD is now at 0608200 fourth commit
➜  undo git:(main) git status
On branch main
nothing to commit, working tree clean
➜  undo git:(main) git log --oneline
0608200 (HEAD -> main) fourth commit
50840de third commit
5a999a7 second commit
6c98eb0 first commits
(END)

revert

revert 和 reset 有点像,但是 revert 会保留之前的 commit,将文件放到 working directory 中,并且创建一个新的 commit 说明之前的 commit 被 revert 了。

举例说明:

➜  undo git:(main) git log --oneline
fbd7250 (HEAD -> main) mistake commit2
2f0f2ce mistake commit
0608200 fourth commit
50840de third commit
5a999a7 second commit
6c98eb0 first commits
(END)

➜  undo git:(main)git add .
➜  undo git:(main)git commit -m "mistake commit"
[main 2f0f2ce] mistake commit
 3 files changed, 36 insertions(+), 1 deletion(-)
➜  undo git:(main) git add .
➜  undo git:(main)git commit -m "mistake commit2"
[main fbd7250] mistake commit2
 1 file changed, 1 insertion(+)
➜  undo git:(main) git log --oneline
➜  undo git:(main) git revert 0608200
error: Your local changes to the following files would be overwritten by merge:
        git.md
Please commit your changes or stash them before you merge.
Aborting
fatal: revert failed
➜  undo git:(main)git revert 0608200
Auto-merging cat.txt
CONFLICT (content): Merge conflict in cat.txt
Auto-merging dog.txt
CONFLICT (content): Merge conflict in dog.txt
Auto-merging git.md
CONFLICT (content): Merge conflict in git.md
error: could not revert 0608200... fourth commit
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git revert --continue".
hint: You can instead skip this commit with "git revert --skip".
hint: To abort and get back to the state before "git revert",
hint: run "git revert --abort".
➜  undo git:(main)git add .
➜  undo git:(main)git revert --continue
[main 6c50464] Revert "fourth commit"
 2 files changed, 1 insertion(+), 1 deletion(-)
 delete mode 100644 wrongfile.txt
➜  undo git:(main) git status
On branch main
nothing to commit, working tree clean
➜  undo git:(main) git log --oneline
6c50464 (HEAD -> main) Revert "fourth commit"
fbd7250 mistake commit2
2f0f2ce mistake commit
0608200 fourth commit
50840de third commit
5a999a7 second commit
6c98eb0 first commits
(END)

可以看到,working tree clean 标记修改的文件已经没有了,但是修改的 commits 还存在。

从个人经验上来说,我用 revert 就是为了修正某些已经实现的功能(by fixing one bug we created more bugs),但是别的同事机器上已经有了那个 commits,不可能说重改整个历史,这样别人做的 commits 也没有了。

即,如果所有的变化都是本地的,那么使用 reset 会方便些。如果变化推到了 remote,但是 没有其他的同事 使用这个 branch,使用 reset 也可以。否则就应该使用 reset。

reference

  • HEAD and ORIG_HEAD in Git

  • What is HEAD in Git?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/13407.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【SCI电气】考虑不同充电需求的电动汽车有序充电调度方法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

从单兵作战到生态共创,纵目科技打响智驾2.0新战役

4月18日&#xff0c;第十二届上海国际汽车工业展览会&#xff08;简称&#xff1a;2023上海车展&#xff09;在上海国家会展中心盛大启幕。纵目科技携最新自动驾驶解决方案——Amphiman 3000、8000行泊一体解决方案、Trinity 3000、8000舱行泊一体解决方案以及众多摄像头产品强…

V2.4版本商超标签专用路由器

PICK_Router_V2.4 产品参数 产品型号 PICK_Router_V2.4 尺寸(mm) 21*14*4.3mm 工作温度 -10-70℃ 产品重量 465g 供电方式 DC12V or POE 工作频率 2.4G 通信速率 50-250kbps 通信方式 10/100Mbps有线网络&2.4G 通信半径 30m 支持标签数量 >10000…

opengl绘制三角形

1.绘制两个三角形 GLfloat vertices1[] { 0.5f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, 0.5f, 0.0f } GLfloat vertices2[] { 0.5f, -0.5f, 0.0f, -0.5f, 0.5f, 0.0f&#xff0c; -0.5f, -0.5f, 0.0f } 也可以用索引的方式&#xff1a; GLfloat vertices[] { 0.5f, 0.5f, 0…

浅谈数字化工厂五大核心系统

一、什么是数字化工厂 数字化工厂是将数字技术应用于工厂生产、管理和运营中的一种方式&#xff0c;可以帮助企业提高生产效率和质量&#xff0c;降低成本和风险&#xff0c;提高竞争力和市场份额。数字化工厂是中小制造业企业自主建设制造业信息化的途径。 简道云数字化工厂解…

电脑开机出现英文字母开不了机U盘重装系统教学

电脑开机出现英文字母开不了机U盘重装系统教学。有用户电脑开机之后出现了错误代码字母&#xff0c;无法正常的开机了。遇到这个问题要怎么去进行系统的重新安装呢&#xff1f;一起来看看以下的具体解决方法教学吧。 准备工作&#xff1a; 1、U盘一个&#xff08;尽量使用8G以上…

WiFi 时钟

WiFi 时钟有很多开源项目的。但是&#xff0c;成品往往代码一大篇&#xff0c;看起来有些上头。加上有些库和环境的版本变迁&#xff0c;编译报错排查起来很是费劲。于是从头捋一遍&#xff0c;一步一步的过程&#xff0c;容易上手&#xff1a; 准备工作&#xff1a; a 零件&…

【天梯赛补题】

175对我这种蒟蒻好难&#xff0c;&#xff0c;&#xff0c; L1-6剪切粘贴 题目详情 - L1-094 剪切粘贴 (pintia.cn) 天梯赛&#xff1a;L1-094 剪切粘贴_scarecrow133的博客-CSDN博客 本蒟蒻看到字符串就害怕&#xff0c;一看就没思路&#xff0c;果断跳过了…… 等佬佬讲…

《面试1v1》java注解

我是 javapub&#xff0c;一名 Markdown 程序员从&#x1f468;‍&#x1f4bb;&#xff0c;八股文种子选手。 面试官&#xff1a;接下来&#xff0c;聊聊Java的注解,它们到底有什么用? 候选人&#xff1a; 注解的用处主要三个: 第一个,编译期使用。比如Override确保你正确重…

Vue 条件语句

文章目录 Vue 条件语句条件判断v-ifv-elsev-else-ifv-show Vue 条件语句 条件判断 v-if 条件判断使用 v-if 指令&#xff1a; v-if 指令 在元素 和 template 中使用 v-if 指令&#xff1a; <div id"app"><p v-if"seen">现在你看到我了<…

自阿里P8爆出内部1031道java面试题后,在Boss直聘狂拿千份Offer

开始之前我问大家几个问题&#xff0c;看大家是如何思考的&#xff1a; 1.程序员一定要去一线城市漂泊吗&#xff1f;在自己家乡如何拿到一份满意的薪水&#xff1f; 2.程序员被裁员、找不到工作&#xff0c;代表什么&#xff1f; 3.程序员一定要进一线大厂吗&#xff1f;你…

LeetCode热题HOT100:单词拆分、环形链表 II、LRU 缓存

LeetCode热题HOT100 139. 单词拆分 题目&#xff1a;给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 注意&#xff1a;不要求字典中出现的单词全部都使用&#xff0c;并且字典中的单词可以重复使用。 示例 1&#xf…

一个从培训学校走出来的测试工程师自述....

简单介绍一下我自己&#xff0c;1997年的&#xff0c;毕业一年了&#xff0c;本科生&#xff0c;专业是机械制造及其自动化。 在校度过了四年&#xff0c;毕业&#xff0c;找工作&#xff0c;填三方协议&#xff0c;体检&#xff0c;入职。我觉得我可能就这么度过我平平无奇的…

D. Ehab and the Expected XOR Problem(构造 + 异或和)

Problem - D - Codeforces 给出两个整数nn和xx&#xff0c;构造一个满足以下条件的数组&#xff1a; 对于数组中的任何元素aiai&#xff0c;1≤ai<2n1≤ai<2n&#xff1b; 没有非空的子段&#xff0c;其位数XOR值等于00或xx、 它的长度ll应该是最大的。 一个序列bb是一个…

Spring更简单的读取和存储对象

1.存储对象 通过注解来替代配置&#xff0c;依然需要配置扫描包的类对象 1.配置扫描路径 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001…

Amazon Linux2部署安装Jenkins

先决条件 服务器配置要求 256 MB of RAM 1 GB of drive space (although 10 GB is a recommended minimum if running Jenkins as a Docker container) 需要部署安装JDK环境部署安装的Jenkins版本为Version 2.400 部署安装JDK 1. 下载JDK软件包 wget https://corretto.aws/…

c++积累11-强制类型转换运算符(static_cast/reinterpret_cast/const_cast/dynamic_cast)

1、背景 将类型名作为强制类型转换运算符的做法是C语言的老式做法&#xff0c;C为保持兼容而予以保留。强制类型转换是有一定风险的&#xff0c;C引入新的转换机制&#xff0c;主要为了客服C语言转换的三个缺点&#xff1b; 1、没有从形式上体现转换功能和风险的不同。 例如&a…

深度强化学习——第一次知识小结(3.5)

一、策略网络的小结&#xff1a; 重要概念回顾&#xff1a; 1、动作价值函数QΠ(st,at) 动作价值函数是未来奖励总和Ut的条件期望&#xff0c;如果已知了策略函数Π与当前的状态st&#xff0c;QΠ就可以对所有的动作a打分&#xff0c;以此来决定选择哪个a 其实顾名思义就是…

【分布式版本控制系统Git】| 国内代码托管中心-Gitee、自建代码托管平台-GitLab

目录 一&#xff1a;国内代码托管中心-码云 1. 码云创建远程库 2. IDEA 集成码云 3. 码云复制 GitHub 项目 二&#xff1a;自建代码托管平台-GitLab 1. GitLab 安装 2. IDEA 集成 GitLab 一&#xff1a;国内代码托管中心-码云 众所周知&#xff0c;GitHub 服务器在国外&…

二:伙伴系统

内核空间内存分配 目录 内核空间内存分配 伙伴系统 首先从内核空间开始&#xff0c;讲解内存管理模式。 主要分为三种方式&#xff1a; 这篇文章我们集中注意于伙伴系统 伙伴系统 解决了外部碎片问题&#xff0c;针对大块内存分配设计 Linux中的内存管理的“页”大小为4…