git 常用操作

git 常用操作

前提:不要通过rebase对任何已经提交到公共仓库中的commit进行修改(你自己一个人玩的分支除外)

1. 撤销 git add

撤销所有的已经 add 的文件

git reset HEAD -- .

撤销某个文件或文件夹

git reset HEAD -- filename

2. 撤销 git commit

git reset --soft HEAD^

HEAD^的意思是上一个版本,也可以写成HEAD~1
如果你进行了2次commit,想都撤回,可以使用HEAD~2

其他参数解析:

  • --soft
    不删除工作空间改动代码,撤销commit,不撤销git add .
  • --mixed【默认】
    不删除工作空间改动代码,撤销commit,并且撤销git add .
    这个为默认参数, git reset --mixed HEAD^ 和 git reset HEAD^ 效果是一样的。
  • -- hard
    删除工作空间改动代码,撤销commit,并且撤销git add .

补充:如果该仓库到目前为止只有commit过一次代码,则会报错:

$ git reset HEAD^
fatal: ambiguous argument 'HEAD^': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

3. git log 查看简洁的提交记录

# 只显示提交 ID 和 提交信息
git log --oneline

4. git reset

  • 工作区:ls 查看
  • 暂存区:git ls-files
  1. soft:git reset --soft 版本ID
    v1 v2 v3(这里我们回退到 v2)
    使用 git status 查看仓库状态:提示我们 files3 是一个新文件,因为 file3 这个文件是在 v3 版本才添加的,所以对于 v2 来说,这个 file3 就是一个新文件,这时我们就可以修改一下 file3 的内容,然后重新添加暂存和提交一下就可以了

  2. hard:
    git reset --hard HEAD^
    ls:file3 消失不见(工作区被删)
    git ls-files 暂存区中也不见了

  3. mixed(默认):git reset HEAD^
    工作区存在
    暂存区不见

5. git 中所有参数都是可以回溯的

git reflog
git reset --hard 版本号

6. git diff 查看差异


默认:比较 工作区和暂存区 之间的差异内容
git diff HEAD:比较 工作区 和 版本库 之间的差异
git diff -cached:比较 暂存区 和 版本库 之间的差异
git diff 版本1 版本2:比较 2个版本的 差异内容

7. 忽略文件 .gitignore


8. 在 VSCode 中使用 Git

9. Git 实用操作【objective打开对话框】!!!

相关博客
https://www.cnblogs.com/baiqiantao/p/13405119.html
联系网站
https://learngitbranching.js.org/?locale=zh_CN

Git Merge(在 Git 中合并两个分支时会产生一个特殊的提交记录,它有两个 parent 节点)

翻译成自然语言相当于:“我要把这两个 parent 节点本身及它们所有的祖先都包含进来。”

我们要把 bugfix 合并到 main 中

咱们再把 main 分支合并到 bugfix 中

因为 main 继承自 bugFix,Git 什么都不用做,只是简单地把 bugFix 移动到 main 所指向的那个提交记录。
现在所有提交记录的颜色都一样了,这表明每一个分支都包含了代码库的所有修改!大功告成!

Git Rebase(实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去)

Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。

# 站在 bugFix 分支上
git rebase main


注意,提交记录 C3 依然存在(树上那个半透明的节点),而 C3' 是我们 Rebase 到 main 分支上的 C3 的副本。

现在唯一的问题就是 main 还没有更新,下面咱们就来更新它吧..

# 现在我们切换到了 main 上,将它 rebase 到 bugFix 分支上
git rebase bugFix


由于 bugFix 继承自 main,所以 Git 只是简单的把 main 分支的引用向前移动了一下而已

测试:

1. 新建并切换到 bugFix 分支
2. 提交一次
3. 切换回 main 分支再提交一次
4. 再次切换到 bugFix 分支,rebase 到 main 上

分离 HEAD

1. 如何在 Git 提交树上移动

我们首先看一下 “HEAD”。 HEAD 是一个对当前所在分支的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。

  • HEAD 总是指向当前分支上最近一次提交记录。大多数修改提交树的 Git 命令都是从改变 HEAD 的指向开始的。
  • HEAD 通常情况下是指向分支名的(如 bugFix)。在你提交时,改变了 bugFix 的状态,这一变化通过 HEAD 变得可见。

2. 分离的 HEAD

git checkout C1


测试:

  1. 从 bugFix 分支中分离出 HEAD 并让其指向一个提交记录。
  2. 通过哈希值指定提交记录。每个提交记录的哈希值显示在代表提交记录的圆圈中

3. 相对引用(^)

通过指定提交记录哈希值的方式在 Git 中移动不太方便。在实际应用时,并没有像本程序中这么漂亮的可视化提交树供你参考,所以你就不得不用 git log 来查查看提交记录的哈希值。

  • 并且哈希值在真实的 Git 世界中也会更长(译者注:基于 SHA-1,共 40 位)。例如前一关的介绍中的提交记录的哈希值可能是 fed2da64c0efc5293610bdd892f82a58e8cbc5d8。舌头都快打结了吧...
  • 比较令人欣慰的是,Git 对哈希的处理很智能。你只需要提供能够唯一标识提交记录的前几个字符即可。因此我可以仅输入fed2 而不是上面的一长串字符。
    使用相对引用的话,你就可以从一个易于记忆的地方(比如 bugFix 分支或 HEAD)开始计算。相对引用非常给力,这里我介绍两个简单的用法:
  • 使用 ^ 向上移动 1 个提交记录
# main 的 parent 节点
git checkout main^
# main 的 第二个 parent 节点
git checkout main^^
  • 使用 ~ 向上移动多个提交记录,如 ~3
git checkout HEAD~4

强制修改分支位置:我使用相对引用最多的就是移动分支。可以直接使用 -f 选项让分支指向另一个提交

# 将 main 分支强制指向 HEAD 的第 3 级 parent 提交
git branch -f main HEAD~3

  • 通过图片可以看出,相对引用为我们提供了一种简洁的引用提交记录 C1 的方式
  • 而 -f 则容许我们将分支强制移动到那个位置

测试:移动 HEAD,main 和 bugFix 到目标所示的位置

# 1. 移动 main
git branch -f main C6
# 2. 移动 bugfix
git branch -f bugfix HEAD~2
# 3. 移动 HEAD
git checkout HEAD~1

4. 撤销变更

在 Git 里撤销变更的方法很多。和提交一样,撤销变更由底层部分(暂存区的独立文件或者片段)和上层部分(变更到底是通过哪种方式被撤销的)组成。我们这个应用主要关注的是后者。

  1. git reset
    git reset 通过把分支记录回退几个提交记录来实现撤销改动。你可以将这想象成“改写历史”。git reset 向上移动分支,原来指向的提交记录就跟从来没有提交过一样。
git reset HEAD~1


2. git revert
虽然在你的本地分支中使用 git reset 很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的哦!
为了撤销更改并分享给别人,我们需要使用 git revert。

git revert HEAD

测试:
要完成此关,分别撤销 local 分支和 pushed 分支上的最近一次提交。共需要撤销两个提交(每个分支一个)。

  • pushed 是远程分支
  • local 是本地分支
# 本地 local
git reset HEAD~1
# 切换到 PUSHED 分支,使用 REVERT
git checkout pushed
git revert HEAD

10. 自由修改提交树【Git Cherry-pick】

整理提交记录:
开发人员有时会说“我想要把这个提交放到这里, 那个提交放到刚才那个提交的后面”

1. git cherry-pick <版本号>...

如果你想将一些提交复制到当前所在的位置(HEAD)下面的话,Cherry-pick 是最直接的方式了。
测试:
只需要简单的将三个分支中的提交记录复制到 main 上就可以了

git cherry-pick C3 C4 C7

2. 交互式的 rebase

当你知道你所需要的提交记录(并且还知道这些提交记录的哈希值)时, 用 cherry-pick 再好不过了 —— 没有比这更简单的方式了。

但是如果你不清楚你想要的提交记录的哈希值呢? 幸好 Git 帮你想到了这一点, 我们可以利用交互式的 rebase —— 如果你想从一系列的提交记录中找到想要的记录, 这就是最好的方法了

交互式 rebase 指的是使用带参数 --interactive 的 rebase 命令, 简写为 -i

如果你在命令后增加了这个选项, Git 会打开一个 UI 界面并列出将要被复制到目标分支的备选提交记录,它还会显示每个提交记录的哈希值和提交说明,提交说明有助于你理解这个提交进行了哪些更改。

在实际使用时,所谓的 UI 窗口一般会在文本编辑器 —— 如 Vim —— 中打开一个文件。 考虑到课程的初衷,我弄了一个对话框来模拟这些操作。

当 rebase UI界面打开时, 你能做3件事:

  1. 调整提交记录的顺序(通过鼠标拖放来完成)
  2. 删除你不想要的提交(通过切换 pick 的状态来完成,关闭就意味着你不想要这个提交记录)
  3. 合并提交(允许你把多个提交记录合并成一个)

# 当你点击下面的按钮时,会出现一个交互对话框。对提交记录做个排序(当然你也可以删除某些提交
git rebase -i HEAD~4


Git 严格按照你在对话框中指定的方式进行了复制

测试:

实际操作

将 C2 drop 掉,并调整 C4、C5 位置

error: could not apply aa5d137... C3
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply aa5d137... C3
Auto-merging table.txt
CONFLICT (content): Merge conflict in table.txt


下面手动解决 新的基线 C1 和 C3 的冲突

修改之后

git add .
git rebase --continue

类似依次处理 C3 与 C5,C5 和 C4 之间的冲突

11. 只取一个提交记录

来看一个在开发中经常会遇到的情况:我正在解决某个特别棘手的 Bug,为了便于调试而在代码中添加了一些调试命令并向控制台打印了一些信息。

这些调试和打印语句都在它们各自的提交记录里。最后我终于找到了造成这个 Bug 的根本原因,解决掉以后觉得沾沾自喜!

posted @ 2024-04-27 23:25  爱新觉罗LQ  阅读(3)  评论(0编辑  收藏  举报