git的正确打开方式

本文深入讲解Git的高级用法,包括分支管理、提交历史的整理、提交记录的移动及撤销变更等技巧。涵盖rebase、cherry-pick、reset、revert等命令的实战应用,适合有一定Git基础的开发者进阶学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Ref:强烈安利

https://learngitbranching.js.org/?locale=zh_CN

1 基础篇

1.1 本地提交

git commit -m "xxx"

1.2 创建分支、分支切换

git branch new_branch_name
git checkout new_branch_name

# 创建一个分支,并切换过去
git checkout -b new_branch_name

1.3 merge合并分支

# 当前在master分支,有一个dev分支
git merge dev

当前状态
image_1e6856guo10bfu0r89mahuqhk9.png-23.7kB
合并之后,产生了一个新提交
image_1e685aes4j5n2u713kte5jth6m.png-32.9kB

1.4 rebase合并分支

rebase合并分支是更高级的合并,也是更推荐的一种合并。Rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。

Rebase 的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 Rebase 的话,代码库的提交历史将会变得异常清晰。
当前状态,在bugFix分支
image_1e685fvjn1kc119fs1eio15f737k13.png-17.1kB
执行

git rebase master

合并之后状态,相当于把bugFix之前所在的c3状态复制了一份放到了master分支的下面rebase的意思像是,给当前的节点重新找一个基地(父节点)。
image_1e685h8ft1nmv1pjhpr1fqk120u1g.png-17.9kB

2 高级篇

2.1 分离HEAD

HEAD 是一个对当前检出记录的符号引用 —— 也就是指向你正在其基础上进行工作的提交记录。**HEAD 总是指向当前分支上最近一次提交记录。**大多数修改提交树的 Git 命令都是从改变 HEAD 的指向开始的。HEAD 通常情况下是指向分支名的(如 bugFix)。在你提交时,改变了 bugFix 的状态,这一变化通过 HEAD 变得可见。

执行命令,就会把HEAD从指向master分离出来,指向一个具体的提交记录

git checkout c2

image_1e685qn5v1g2f12dd1apt1bk4guk1t.png-12.5kB

2.2 相对引用

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

  • 使用 ^ 向上移动 1 个提交记录
  • 使用 ~<num> 向上移动多个提交记录,如 ~3

git checkout后面可以跟分支,hash值,HEAD,非常灵活。

git checkout 分支名/提交记录hash值/HEAD   相对引用(^/~<num>)

举例,当前状态
image_1e6862m9b1m8n1vh51l0c1sc0he42a.png-9.4kB
执行

git checkout master^

结果
image_1e6864bt113ss1euqupd1dbhh6v2n.png-12.3kB

2.3 撤销变更

2.3.1 reset:真正的回退

git reset通过把分支记录回退几个提交记录来实现撤销改动。你可以将这想象成“改写历史”。git reset 向上移动分支,原来指向的提交记录就跟从来没有提交过一样。
当前状态
image_1e686eulk1v4kt7e1nhesit1jol34.png-9.2kB
执行

git reset HEAD^

结果,
image_1e686flqrcrsf8fp4s1suj1m643h.png-9.3kB

2.3.2 revert(推荐):以进为退

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

git revert HEAD^

结果
image_1e686i2laimq5ki1cqj32d123b3u.png-10.6kB

在我们要撤销的提交记录后面居然多了一个新提交!这是因为新提交记录C2'引入了更改 —— 这些更改刚好是用来撤销C2这个提交的。也就是说C2'的状态与C1是相同的。

总结:使用git revert可以让我们一直向前!!

3 移动提交记录

到现在我们已经学习了 Git 的基础知识 —— 提交、分支以及在提交树上移动。 这些概念涵盖了 Git 90% 的功能,同样也足够满足开发者的日常需求。

然而, 剩余的 10% 在处理复杂的工作流时(或者当你陷入困惑时)可能就显得尤为重要了。接下来要讨论的这个话题是**“整理提交记录” —— 开发人员有时会说“我想要把这个提交放到这里, 那个提交放到刚才那个提交的后面”,** 而接下来就讲的就是它的实现方式,非常清晰、灵活,还很生动。

3.1 cherry-pick摘樱桃

git cherry-pick <提交号hash>

如果你想将一些提交复制到当前所在的位置(HEAD)下面的话,Cherry-pick 是最直接的方式了。我个人非常喜欢 cherry-pick,因为它特别简单。

当前状态
image_1e6871gbi3b8lml149lg8nqel4b.png-18.1kB

执行命令

git cherry-pick c2 c4

执行结果,可以看到像是直接把C2、C4复制了一份放到了当前节点下面
image_1e6872u78iuqhsoq1eqrl13at4o.png-20.8kB

cherry-pick的厉害之处就在于保持提交记录的线性,因为它是以复制的方式完成工作。至此,有没有一种神奇的感觉,git命令的精髓其实就是保持提交记录的线性,因为这样的历史记录就会非常清晰。

3.2 交互式rebase

cherry-pick需要你检查git log看到hash值才能像摘樱桃那样去操作。更方便的是有一种交互式的rebase,图形化摘樱桃,而且任意拖动调整顺序。

当前状态,查看git log,提交记录按时间线由最新到最老有 test2、test1、version1.0
执行

git rebase -i HEAD~2

出现交互式vim
image_1e6880t7rvg25nv1fhssk91o9j5i.png-88kB
可以在vim编辑器中使用列出的命令,也可以调整上下顺序。常用命令pickdrop
查看git log,发现只剩下了v1.0test1和test2就像没有存在过一样。

4 杂项

4.1 只取一个提交记录

当前状态,修改bug中间加入了printf帮助调试,在最新的c4解决了bug,想只把c4的内容合并到master下面,printf的内容并不想要,就是用cherry-pick或者rebase -i吧!

image_1e688958dp86p4h1u0o133727g5v.png-21.5kB

git checkout master
git cherry-pick c4

执行结果
image_1e688gm4ggm91cr3vqn1clrluf6c.png-36.2kB

或者

git rebase -i bugFix~3
git branch -f master bugFix # 把master指向bugFix,也就是把成c4加到了master中

image_1e688suevjql16ck1keo1artnev6p.png-33.8kB

4.2 提交的技巧

4.2.1 提交技巧1

接下来这种情况也是很常见的:你之前在 newImage 分支上进行了一次提交,然后又基于它创建了caption 分支,然后又提交了一次。

此时你想对的某个以前的提交记录进行一些小小的调整。比如设计师想修改一下newImage 中图片的分辨率,尽管那个提交记录并不是最新的了。

我们可以通过下面的方法来克服困难:

先用git rebase -i将提交重新排序,然后把我们想要修改的提交记录挪到最前
然后用commit --amend来进行一些小修改
接着再用git rebase -i来将他们调回原来的顺序
最后我们把master 移到修改的最前端(用你自己喜欢的方法),就大功告成啦!
当然完成这个任务的方法不止上面提到的一种(我知道你在看 cherry-pick 啦),之后我们会多点关注这些技巧啦,但现在暂时只专注上面这种方法。 最后有必要说明一下目标状态中的那几个’ —— 我们把这个提交移动了两次,每移动一次会产生一个 ';而C2上多出来的那个是我们在使用了amend 参数提交时产生的,所以最终结果就是这样了。

也就是说,我在对比结果的时候只会对比提交树的结构,对于'的数量上的不同,并不纳入对比范围内。只要你的 master分支结构与目标结构相同,我就算你通过。

初始状态
image_1e6891kqj1kta10jkjngdfg976.png-16.9kB

git rebase -i c1 

执行后状态,把c3,c2复制了一份,并且改变了顺序
image_1e689a13uejc1o6410ln1e75uma7j.png-31.4kB

git commit --amend # 通过创建新的提交来替换当前分支

image_1e689bfhg81b1l1a1bn41vm3g2l80.png-14.9kB

c3' ,c2''复制了一份,并且改变了顺序

git rebase -i c1 

image_1e689hbum3621645c8mhba1n8c8d.png-37.9kB

git branch -f master c3'' # master指向最新的

image_1e689lp9l1i3e10ch12binl11l7t8q.png-36.6kB

4.2.2 提交技巧2

rebase -i 对提交记录进行重新排序,只要把我们想要的提交记录挪到最前端,我们就可以很轻松的用--amend 修改它,然后把它们重新排成我们想要的顺序。但这样做就唯一的问题就是要进行两次排序,而这有可能造成由rebase 而导致的冲突。下面还是看看 git cherry-pick是怎么做的吧。

要在心里牢记cherry-pick可以将提交树上任何地方的提交记录取过来追加到HEAD上**(只要不是 HEAD 上游的提交就没问题)。**

当前状态
image_1e689q3krj6sc9892l1q0c1p697.png-17.4kB

git cherry-pick c2

image_1e689qe0l1f7q1maa51n1tbat8r9k.png-18.2kB
仅仅使用cherry-pick也可以达成上一关的目的。

4.3 git tag

你可能会问了:有没有什么可以永远指向某个提交记录的标识呢,比如软件发布新的大版本,或者是修正一些重要的 Bug 或是增加了某些新特性,有没有比分支更好的可以永远指向这些提交的方法呢?

git tag v1 c1

image_1e68a15i315nf18mj64u1t5fij4a1.png-10.1kB

4.4 git describe

由于标签在代码库中起着“锚点”的作用,Git 还为此专门设计了一个命令用来描述离你最近的锚点(也就是标签),它就是 git describe!
**Git Describe 能帮你在提交历史中移动了多次以后找到方向;**当你用git bisect(一个查找产生 Bug 的提交记录的指令)找到某个提交记录时,或者是当你坐在你那刚刚度假回来的同事的电脑前时, 可能会用到这个命令。
image_1e68a4tmd130t16n0e9q17c71s1dae.png-50.4kB

找到某个分支的最近的一个版本号,快速恢复到那个版本!!

5 高级篇

5.1 把众多的分支rebase到master分支

初始状态,要求把众多的分支rebase到master分支,这就是项目代码管理员干的事呀!!
image_1e68ajbv51t1e1mfh59912cj16raar.png-49.8kB
合并c3到master下面

git checkout bugFix
git rebase master

合并c4,c5,c6到bugFix下面
image_1e68aq1c316gr170be8vc20ipnb8.png-15.9kB

git checkout side
git rebase -i bugFix

image_1e68as78hk5f1u3j14091p551injbl.png-29.3kB

合并c7到side分支下面

git checkout another
git rebase -i side 

image_1e68b01heas2q651rkt1m5l8upc2.png-35.8kB

master移动到最前面,完成

git checkout master
git rebase another

完成上述步骤更快的一种方式,。。。。。还不知道。。。

...

5.2 存在多个父亲,选择父提交记录

操作符^~符一样,后面也可以跟一个数字。

但是该操作符后面的数字与~ 后面的不同,并不是用来指定向上返回几代,而是指定合并提交记录的某个父提交。还记得前面提到过的一个合并提交有两个父提交吧,所以遇到这样的节点时该选择哪条路径就不是很清晰了。

Git 默认选择合并提交的“第一个”父提交,在操作符 ^后跟一个数字可以改变这一默认行为。

初始状态
image_1e68cpcktj0p17ei15so998lqie3.png-18.7kB

git checkout HEAD~^2~2 # 前进一个,第二个父亲,前进2个

image_1e68cglsd1rv41su6qs11ejv1uh4cs.png-21.4kB

初始状态
image_1e68cnajj1ulp164opiame66d6d9.png-39kB

git checkout HEAD~^2~ -b bugWork # 移动到指定位置,并创建分支

结果
image_1e68cob9s12ru1jsu1llh9cqvpsdm.png-40.9kB

5.3 纠缠不清的分支

image_1e68cr27r109v1sld1vih1tfu1cs8eg.png-26.2kB
初始状态
image_1e68de8lr4nabe37u1rdqi4vet.png-21.5kB
目标结果
image_1e68df3le1qs11s541hdfkukcrrfa.png-40.9kB
执行过程,最优只要5条命令

git checkout one
git cherry-pick c4 c3 c2
git checkout two
git cherry-pick c5 c4' c3' c2'
git branch -f three c2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值