git提交分支

本文详细介绍了Git的分支操作,包括创建、切换、合并分支以及解决冲突的方法。同时,解析了.gitignore文件的用途和规则,指导如何忽略不需要版本控制的文件。此外,讲解了Git的版本回退、cherry-pick操作,以及merge和rebase的区别和应用场景。文章最后讨论了何时使用merge和rebase,以及它们在团队协作中的注意事项。
摘要由CSDN通过智能技术生成

1. git提交分支相关

  • 在本地新建分支,保证和远程分支一样

    git checkout -b 分支名
    

    如果分支已存在,只需要切换的话

    git checkout 分支名
    
  • 提交前先把代码拉下来更新一下,确保不会覆盖别人的代码

    git pull origin 远程分支
    
  • (如果有)解决冲突

git diff  // 然后查看冲突的原因
  • 查看git状态(哪些还未提交)
git status
  • 提交到缓存区
git add .
  • 提交到本地仓库
git commit -m '我这次提交是为了干啥'
  • 提交到远程仓库(线上仓库)
git push origin 分支名		
  • (如果不存在)本地建立一个你要合并的分支(如你在a分支上开发,现在要和b分支merge并提交到b分支上)
git checkout -b 要合并的分支b
  • 把要合并分支的代码拉下来
git pull origin 要合并的分支b
  • 在本地合并到b分支
git merge 要合并的分支b
  • 如果报错,那么查看git状态
git status

2. 关于.gitigonore 文件详解

这个文件的完整文件名就是“.gitignore”,注意最前面有个“.”。这

一般来说每个Git项目中都需要一个“.gitignore”文件,这个文件的作用就是告诉Git哪些文件不需要添加到版本管理中。

实际项目中,很多文件都是不需要版本管理的,比如Python的.pyc文件和一些包含密码的配置文件等等。

这个文件的内容是一些规则,Git会根据这些规则来判断是否将文件添加到版本控制中。

过滤规则:

/mtk/ 过滤整个文件夹

*.zip 过滤所有.zip文件

/mtk/do.c 过滤某个具体文件

被过滤掉的文件在push的时候不会上传。

需要注意的是,gitignore还可以指定要将哪些文件添加到版本管理中:

!*.zip

!/mtk/one.txt

版本规则:

唯一的区别就是规则开头多了一个感叹号,Git会将满足这类规则的文件添加到版本管理中。

假如只需要管理/mtk/目录中的one.txt文件,这个目录中的其他文件都不需要管理。就需要使用这个!规则:

/mtk/

!/mtk/one.txt

如果在创建.gitignore文件之前就push了项目,那么即使你在.gitignore文件中写入新的过滤规则,这些规则也不会起作用,Git仍然会对所有文件进行版本管理。

出现这种问题的原因就是Git已经开始管理这些文件了,所以你无法再通过过滤规则过滤它们。

重点:在项目开始就创建.gitignore文件的习惯,否则一旦push,处理起来会非常麻烦。

3. git的版本回退

因为在合并分支的过程中,变更太多,是本地环境配置的问题,需要回退到上一个版本,然后再重新提交。

git log
  • 定义:该命令显示从最近到最远的提交日志。每一次提交都有对应的 commit id和 commit message。
image-20220501172511044
git log --pretty=oneline
  • 可以将版本号和描述内容在一行内显示,使得输出更加简洁一些
image-20220501172550786
git reset --hard id
  • 定义:根据 id 回退到指定的版本,一般要回退的版本号的前7位即可
git push origin HEAD --force
  • 推送到本地到远程仓库:让远程仓库代码你本地一样,到当前本地的版本。
git reflog
  • 定义:查看命令操作的历史

    查找到需要的 操作id,依旧使用

    *git reset --hard id*
    

    可以回退到先前的版本。

4. git的cherry-pick

cherry-pick 的翻译是择优挑选,使用git cherry-pick命令,可以选择将现有的一个或者多个提交的修改引入当前内容。

那么,什么情况下会有到这么不常见的命令呢?

假设你现在正在开发一个项目,有一个功能分支 feature,开发分支 develop。 feature 有3个提交,分别是 A ,B ,C 。develop 分支只想加入 C 功能, 此时合并操作无法满足,因为直接合并 feature,会将3个提交都合并上,我想合并就只有 C,不要 A,B。此时就需要挑樱桃大法–cherry pick!

具体的做法:

1.切换到 develop 分支。
2.通过 git log feature,找到 C 的 SHA1 值。
3.通过 git cherry-pick <C的SHA1> ,将 C 的修改内容合并到当前内容分支 develop 中。
4.若无冲突,过程就已经完成了。如果有冲突,按正常冲突解决流程即可。
image-20220501172636309

从上面简单的小例子上看,我想,小伙伴们,都应该已经对 merge 和 cherry-pick 有了大概的区分,这里做下对比,让大家有个清晰明确的掌握,防止似是而非,以后误操作。

git merge :将两个提交历史合并。
git cherry-pick:将提交对应的内容合并。

这里,非常需要明确的一点,commit 代表的是修改!

例中,提交 C 的内容,就是对比 B 上面做的修改,可能是创建了一个文件,或者修改了一个词语。那么 C 内容就是一个文件的添加,和一个词语的修改。

以提交 C 为结束点的提交历史,实际内容是提交 C 和 C 之前所有的修改。

cherry-pick 操作的对象就是 commit。
merge 操作的对象就是 commit history。

例子:

利用cherry-pick,可以将一个分支中的修改的内容合并到另一个分支上。如要将lyrisgao中的某一个功能提交的内容合并到addsomeparms

image-20220501172713045
  • 合并之后,可以发现 提交的并不是真正的分支的内容,是分支内容的复制品,因为两者的SHA1的值是不同的,可以确定是两个提交。

    image-20220501172726737

4.1 cherry-pick 其他常用命令

  • 挑选多个提交合并,提交之间用空格相隔。例如,想挑选1号和3号的,就可以用git cherry-pick 4d2951 e4cdff9命令一步到位了。
git cherry-pick <commits>
  • 挑选一个范围的多个提交合并,但是这个语法对应操作区别是左开右闭,不包含start-commit。另外要注意两个commit 之间要求有连续关系的,并且前者要在后者之前,顺序不能颠倒。
git cherry-pick <start-commit>..<end-commit>
  • 这个和上面一样,区别就是加了一个^符号,就变成闭区间了,包含 start-commit。
git cherry-pick <start-commit>^..<end-commit>
  • 挑选 branch 最顶端的提交。例如挑选 3 号樱桃可以用git cherry-pick develop。

    git cherry-pick <branch name>
    
    git cherry-pick --continue  //继续下个操作
    git cherry-pick --quit //退出
    git cherry-pick --abort //停止本次操作
    

    以上是关于 cherry-pick 操作控制命令,当 cherry-pick 多个提交时,假设遇到冲突,–continue继续进行下个,–quit结束 cherry-pick 操作,但是不会影响冲突之前多个提交中已经成功的,–abort直接打回原形,回到 cherry-pick 前的状态,包括多个提交中已经成功的。

5. git merge 和 git rebase

git rebase 和 git merge是git合并分支的两种方式,然而他们却采用了不同的工作方式,以下面的一个工作场景说明其区别:

image-20220501172807189

场景:

下图所示:当feature分支有新的需求提交,同时,master 分支也有修改。

这时,如果要将master 上新的提交合并到你的feature分支上,我们有两种选择:merging or rebasing

5.1 merge

执行以下命令:

git checkout feature
git merge master
或者执行:
git merge master feature
此时在feature上git 自动会产生一个新的commit(merge commit)

注意:

git 本地分支合并master分支代码 : 提示为 git merge Already up-to-date.
原因在于merge之前,master分支的代码不是最新代码

做法:
1.应该先切换到master分支
git checkout master

2.拉取代码
git pull origin master

3.再切换到要合并master的分支
git checkout 分支

4.合并代码
git merge master
有冲突则解决冲突

当使用 git log 查看时,发现已经多了一个commit

image-20220501172841032

5.2 merge 特点

merge 特点:自动创建一个新的commit
当合并时遇到冲突,修改后重新commit即可
优点:将commit的实际情况进行记录,便于以后查看
缺点:由于每次merge会自动产生一个merge commit,所以在使用一些git 的GUI tools,如果commit频繁,这样会使得feature分支很杂乱,这时可以考虑使用rebase来进行合并处理。

5.3 rebase

本质是变基,即找公共祖先

执行以下命令:

git checkout feature
git rebase master
image-20220501172907076

5.4 rebase 特点

rebase 特点:将commit历史进行合并
优点:项目历史比较简单,少了merge commit
缺点:当发生冲突时不容易定位问题,因为re-write了history

合并时如果出现冲突需要按照如下步骤解决

1.修改冲突部分
2.git add
3. git rebase --continue
(如果第三步无效可以执行 git rebase --skip)
4.不要在git add 之后习惯性的执行 git commit命令

The Golden Rule of Rebasing rebase 的黄金法则
never use it on public branches(不要在公共分支上使用)
比如说如下场景:如图所示

image-20220501172920139

如果你rebase master 到你的feature分支:

rebase 将所有master的commit移动到你的feature 的顶端。问题是:其他人还在original master上开发,由于你使用了rebase移动了master,git 会认为你的主分支的历史与其他人的有分歧,会产生冲突。

所以在执行git rebase 之前 需要认真考虑,

会有其他人看这个分支么?
if YES 不要采用这种带有破坏性的修改commit 历史的rebase命令
if NO ok,随你便,可以使用rebase

将几个commit log 合并一个

git rebase -i 版本号(需要合并的那几个commit log 之前的那一个commit版本号)
  • 之后会显示以下界面

    image-20220501172954780

    pick : 代表合并后的提交用这个提交的注释;
    s : squash命令的简写,代表合并提交中包含这个提交;
    d : 代表合并提交中排除这个提交。

  • wq保存之后

    git rebase --continue
    
  • 设置注释之后

  • 完成

    以上是将连续的commit id合并,假如是不连续的话,那么你也是拿最早的commit id来执行git rebase -i commit id,然后进入弹出框,你会看到pick中没有最早你要合并的那个commitid,这里你需要按照列表的格式把最早的commit id复制到顶部,格式就是 pick commit id XXX,这个XXX就表示注释(可有可无),然后再把你要合并的几个commit一定复制到当前这个新加的pick下面,然后修改成 (s commit id XXXX),有几个写几个,把重复的去掉,然后保存即可。

5.5 总结

尽量不要在公共分支使用 rebase
本地和远端对应同一条分支,优先使用 rebase ,而不是 merge

因为往后放的这些 commit 都是新的,这样其他从这个公共分支拉出去的人,都需要再 rebase,相当于你 rebase 东西进来,就都是新的 commit 了

1-2-3 是现在的分支状态
这个时候从原来的 master , checkout 出来一个 prod 分支
然后 master 提交了4.5,prod 提交了6.7
这个时候 master 分支状态就是1-2-3-4-5,prod 状态变成1-2-3-6-7
如果在 prod 上用 rebase master , prod 分支状态就成了1-2-3-4-5-6-7
如果是 merge
1-2-3-6-7-8
… |4-5|
会出来一个8,这个8的提交就是把4-5合进来的提交

merge 和 rebase 实际上只是用的场景不一样

​ 更通俗的解释一波:

  • 比如 rebase,你自己开发分支一直在做,然后某一天,你想把主线的修改合到你的分支上,做一次集成,这种情况就用 rebase 比较好。把你的提交都放在主线修改的头上。

  • 如果用 merge,脑袋上顶着一笔 merge 的8,你如果想回退你分支上的某个提交就很麻烦,还有一个重要的问题, rebase 的话,本来我的分支是从3拉出来的, rebase 完了之后,就不知道我当时是从哪儿拉出来的我的开发分支

  • 同样的,如果你在主分支上用 rebase , rebase 其他分支的修改,是不是要是别人想看主分支上有什么历史,他看到的就不是完整的历史课,这个历史已经被你篡改了

结论:

想要干净的历史,少了merge commit的线性历史树,选择git rebase
而如果你想保留历史记录,并且想要避免重写commit history的风险,使用git merge

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值