当前位置:   article > 正文

git使用经验小记_gitlab拉取指定版本

gitlab拉取指定版本

1. 写在前面

实习的时候公司的项目代码往往多人协同合作, 需要用到git工具,把代码提交到Gitlab上去, 虽然之前学习过Git的简单使用,比如项目代码的克隆到本地,然后修改,push到远程仓库啥的, 但是昨天mentor突然说,你新建一个分支,把你改的代码push到这个新建的分支上,先让测试的同学测试, 测试成功了再合并到master里面去吧。

唉,就这么一句,我就懵逼了,分支是干啥的? 之前都是在GitHub上建立一个项目,只有个master分支,从来没有遇到过这种多人协作的场景,也从没接触过git创建分支呀, 但在mentor面前,又不好意思都说这些东西没接触过, 我发现实习,工具都是默认都会的(即使之前没接触,也得偷摸的学会),所以应了一声之后,就赶紧先偷摸的学了一波(这些可不是占用工作时间,得额外花时间自己补,下班之后摸索的), 所以下面把在多人协作的时候常用的git操作和自己目前的体会和理解整理下来,也方便后面再用到。 当然由于我刚接触到这些,肯定会不全,理解上也会有偏差,但后面虽然使用频率增加,会慢慢补充和修改,先记录下吧。

由于时间原因,不具体演示结果,只整理常用的操作,当然,也整理下pycharm的Git使用,这东西比命令可是香太多啦,下面这些全是自己摸索,有不对的也欢迎指出来呀!

2. git最常用的几个操作

关于git是啥,怎么安装啥的,这里就不说了, 网上资料一大堆,这里先整理我个人如果用的话,往往常用的几个操作。

首先,下载下Git, 然后完成一些基本的配置:

首先设置你的用户名和邮件地址。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中

# github或者gitlab用到的用户名和邮箱
$ git config --global user.name "John Doe"
$ git config --global user.email "johndoe@example.com"

# 查看基本配置
git config --list
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

然后,配置ssh提交

# 生成秘钥
ssh-keygen -t rsa -C "johndoe@example.com"  # ~/.ssh目录下面会有id_rsa和id_rsa.pub两个文件

cat id_rsa.pub  # 把这个里面的内容复制
  • 1
  • 2
  • 3
  • 4

复制上面的内容之后,打开你的github,进入配置页: Settings – SSH and GPG keys,添加本地生成的ssh秘钥,选择New SSH key(这里已经配置了一个key,如果是未配置秘钥的用户,这里是空的), 把复制的内容贴过来,然后保存:

#测试是否配置成功

用ssh链接git:ssh -T git@github.com 
  • 1
  • 2
  • 3

这样做的原因是后面提交代码的时候,用的是ssh服务,还可以用http服务,不过那个还得每次git push的时候,得输入GitHub用户名和密码登陆太麻烦,而走ssh这个,就可以直接提交。 这样,Git的基本配置就完成了。

下面就是常用操作,首先我经常会先从GitHub上新建一个仓库,然后git clone下来,这样的话,就可以从本地修改,提交了。但注意,git clone的时候复制地址用ssh格式的才行, 啥意思?
在这里插入图片描述

SSH的这个,而不是HTTPS下面的那个。常用操作如下:

# 克隆项目下来
git clone git@github.com:zhongqiangwu960812/AI-RecommenderSystem.git
git clone -b dev_jk http://10.1.1.11/service/tmall-service.git    # 指定拉取某个分支

# 如果新改了某个文件,需要同步到远程

# 如果是新增了某个文件,可以直接
git add 文件名    
git status  # 可以查看修改情况
git commit -m '新加文件'     # 提交说明
git push    # 提交  

# 这样,就搞定了

# 如果是删除了某个或者修改了很多地方等,可以
git add .
git commit -m 'update many'
git push

#  如果是从远程仓库改了文件,需要先拉到本地,让本地和远程保持一致之后再push
git pull
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

这些命令,就是在学校里面自学的命令了, 当时我记得也看到过分支啥的, 但由于场景有限,不知道怎么运用,所以就难理解, 而在公司, 竟然这些才是最基础操作。 下面是昨天刚学习的一些东西:

3. git 分支

关于分支是啥? 这个不整理, 具体原理可以在下面的教程中看,这里我只说针对我现在的情景的一个理解, 就知道为啥场景非常关键了。

公司中,在Gitlab上,一般是一个大组共同维护着一个大项目, 每个人都可以对这个项目根据需求进行修改。

我实习来了之后,拿到的第一个任务,就是迁移接口和队列的操作,就是需要改一些配置啥的, 这时候我git clone下这个项目来之后(这个git clone最好养成习惯, 在本地IDE浏览代码,可比直接在gitlab上切换节省时间太多了)用pycharm打开,然后进行修改。

这时候,我按照需求和mentor指示, 修改完了第一版代码, 然后打算去提测(算是开发完成,去找测试的同学测试), 这时候,由于我的代码没有经过测试,根本不知道能不能运行成功。而测试的同学拿我代码,只能通过gitlab去拿,然后可以code diff,顺便测试等。 那么这时候, 我又不能把代码直接提交到master上, 因为master算是维护最终正确代码,当你代码没有问题的时候才可以合并到上面,而我现在不知道有没有问题,又必须得提交到gitlab, 于是乎,mentor说,你建立个分支就行了,把你代码提交到分支上, 测试的同学测试成功之后,再merge到master上就解决了。

所以有了场景之后,有些东西自然会有感觉,分支现在给我的感觉,仿佛是面临多个需求,需要修改代码的时候,或者多个人共同维护一个项目,但是又不能直接往master提交的时候,分支这时候就起作用了。

这样一个感觉,一开始,整个项目开发流程是一条直线走着,这个叫做master, 分支的意思就是每个人开发的时候, 从当前直线上拉出一个分叉来
在这里插入图片描述
每个人在开发之前,先建立一个分支出来,从分支上进行开发,开发完毕,然后提交merge request,没有问题之后,合并到master上,这条线就能往前进一步, 一点点的多个人把整体项目往前推进,这就是多人合作开发的流程。

我建立分支之后,就可以在这个分支下按照需求进行修改,这样还不影响最终代码,当有好几个版本,或者有好几个需求的时候,就非常适合建立分支,一个分支对应一个需求,开发完毕,进行push到分支,接着从另一个分支上开发,这样互不影响,最后还可以merge起来。

如何建立呢?

# 分支的创建与切换, 也可以直接用一行代码: git checkout -b 分支名
git branch 分支名
git checkout 分支名

# 查看目前在哪个分支已经状态, *表示目前所在的分支
git status

# 将本地分支关联到远程分支上
git push --set-upstream origin 分支名

# 把本地分支上的修改,同步到远程
git push  # 前提当前在本地分支上  否则 用下面这个
git push origin 本地分支名:远程分支名

# 删除远程的分支
git push origin :远程分支名   或者 git push origin --delete 远程分支名

# 查看分支
git branch   # 本地分支
git branch -r   # 远程分支
git brance -a  # 查看所有分支
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

当然,上面这些命令估计看了之后就头大了,所以下面还有种非常简单的傻瓜式操作,就是pycharm的Git。不过,还是建议掌握这些常用的命令,这是在公司进行Git协作的基础,毕竟IDE不会总常有,但命令行是常有的。

4. Pycharm的git

关于这个东西,也是不介绍,直接说是咋用的。 我是先把gitlab上的项目git clone到本地。然后pycharm打开,此时
在这里插入图片描述
左下角这里,会有目前所在的分支,默认的时候是master分支,由于我这里修改了三版代码,所以新建了三个分支。如果面临新需求,可以点击上面的New Brance新建立分支,默认会自动切换到此分支,这时候,就可以肆无忌惮的写代码了。

此时,如果我们修改代码,pycharm会自动标记出来,修改是蓝色,Add之后变成绿色好像是, 修改完代码,我们右键点击项目名称,在里面有个git选项, 在这里吗就能够看到add和commit的操作了,我们可以先Add,把修改的代码放到暂存区,然后进行commit的操作。
在这里插入图片描述

点击commit director之后,就会看到这样的一个界面:
在这里插入图片描述

上面的窗口就会看到自己修改的东西,而下面,可以添加修改描述, 接下来可以直接commit and push,也可以直接commit, 如果是前者,就会自动同步到远程的对应分支上去,如果是后者,还需要push操作才会同步到远程上去。

所以这个就非常方便了, 我今天用的时候,是根据其中一个需求,建立了分支v1,然后修改代码,进行提测,提测的时候测试小姐姐让我提供分支名和commit id(ci id), 我对后面这个又一脸懵逼,这个commit id是这么查的, 命令行输入

git log
  • 1

这里面会显示自己的历史提交
在这里插入图片描述

最近的一次,commit后面那一长串就是comit id了。

完成这个之后, 又面临一个需求,所以又建立的了个v2分支,把代码开发提交测试, 接着新建立一个V3分支,在V2的基础上继续修改代码,此时测试小姐姐说v2上有代码有问题,需要修改,此时我面临的处境在v3分支上新加了新代码。当我切换到v2的时候,发现,呀,这不和v3是一样的了吗? 这我还咋改v2。 然后mentor和我说,你v3改了之后要commit才行呀,这时候,才能看到真正的v2。所以在v3分支上,把修改先commit,此时再切回v2,看到了原来的v2, 再从这个基础上改代码,push到v2分支,再提测就OK了。

然后又从v3的基础上,把新的需求改完,add+commit push即可把之前的commit的,和后又新加的都一块同步到远程仓库,确实非常方便。

所以通过这一天,我算是见识了,之前从没有体会到Git原来是这么玩的呀。 当然,还有merge的需求, 这个由于目前还在分支开发中,没有merge, 所以这个先不写了,后面补上。

时隔两天, 补一下merge了, 因为突然需要用到merge了, 场景是这样子的, 上面我接了2个开发任务, 新建了一个v2分支,去做A需求,这个开发完成之后, 需要进行提测和上线, 在我提测了之后,接着又在v2的基础上,建立了一个新的分支v3做B需求, 这时候, v2测试过了,然后需要上线,所以就merge到了master,然后部署上线。 这时候远程v2分支就没了(merge了嘛)。

接着,我从v3上做新的开发, 做完了之后,本来想提测,这时候发现了个问题,v3是v2merge,上线之前建立出来的, 而v2在merge和上线之前,根据测试那边的反馈是做了些改动的,这时候,就面临着,即使我v3完成了当前的B需求,但A需求v3这个版本是没有管的,也就是即使提测,相当于能满足B需求而A需求又没法满足了,这时候怎么办呢?这是就用到了merge。 这里mentor告诉我的解决办法: 把远程的master(这个是最新的)pull到你本地的master分支,然后把本地的master合并到v3就可以了,再把v3push到远程的v3分支。

所以,merge的意思呢? 是保留最新的改动, 如果把master merge到v3上,由于master是满足了A需求的,merge到v3后,我v3就不需要再管master的各种修改了,统一到了最新的版本上去,基于新的master进行了再开发, 这个是真的学到了。如果感觉说的比较抽象,可以先看看这篇文章, 先了解下从dev合并到master分支是啥意思。 而我master分支合并到dev上,其实相当于这个意思:
在这里插入图片描述

5. git 提交忽略某些文件

这个是和同事在一块Git协作项目的时候学习到的,首先, 对于Git使用,一定要学会善用

git status
  • 1

这个命令会告诉我们目前修改了哪些文件, 但我之前忽略的一项是Untracked files这一项,
在这里插入图片描述
下面这个是告诉我们Git不管这几个文件的。

现在我的一个情况是, 在我本地新建了一个cpp文件,比如helloworld.cpp, 然后编译出了一个可执行文件helloworld, 此时同事告诉我说,只需要把.cpp文件传上去, 可执行文件不要传,但是一般,对于add, 我都是习惯git add ., 把所有修改都push上去。

在这里才发现, 有时候还需要有选择的进行push, 此时有两个方法, 第一个就是git add helloworld.cpp, 具体到上传的文件名,此时没有什么问题, 另外一个就是把helloworld这种文件设置成不可追踪, 也就是放到Untracked files里面去。命令:

git rm --cached helloworld
  • 1

此时再git status, 在Untracked files里面就会出现helloworld, 此时再用

git add . 或者 git add -u  
git commit -m ""
git push
  • 1
  • 2
  • 3

提交的时候, 就不会再有上面这种可执行文件了。

另外,就是git checkout也要好好的利用, 如果在本地修改了某个文件, 但是呢? 发现修改错了,不想保存修改的这个了, 那么就可以使用这个命令回退到原来的文件,具体是这样的:

git status  # 查看修改了哪个文件
git checkout 文件名   # 回退到了之前的版本
  • 1
  • 2

6. master合并到分支再开发(merge vs rebase)

这个问题是这样的, 把远程的代码git clone下来,然后新建立了一个分支,切换到分支上进行开发, 开发完一个模块, git push到远程分支上去。 然后在远程上提交merge 请求, 把分支上的修改合并到了master。

此时,远程的master和本地的master就不一样了

我当时忘了这个问题了, 而是直接又在分支上继续开发,然后git push, 再从远程提交merge请求合并的时候, 就出现了
在这里插入图片描述
出现了冲突, 才意识到这个问题。

这个问题的后续解决,在分支上, 比如zq_dev

git pull origin master
  • 1

把远程的master拉下来,此时应该会出现冲突文件git status
在这里插入图片描述

打开文件,把冲突改掉。然后重新git add + git commit + git push一系列操作。

上面本身的正解,应该是当远程的merge 请求通过了之后,此时远程的master和本地的master已经不一样了。 此时应该在本地master分支上,先把master同步下来,然后再切换到自己的分支

// 切换到主分支
git checkout master

// git pull把远程和本地同步
git pull

// 切换到zq_dev分支
git checkout zq_dev

// 主分支的代码merge到自己的分支, 此时当前分支和master保持一致了
git merge master   // 这句话,现在也可以用一个更高级的命令git rebase master

// 此时再git add, git commit git push一系列操作才可以
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这个操作在合作开发中很重要。 所以这里整理下git merge mastergit rebase master的区别,虽然都是实现先把master的最新代码合并到分支上。

首先我们应该明白git rebase是用来处理git merge命令所处理的同样的问题。这两个命令都用于把一个分支的变更整合进另一个分支——只不过他们达成同样目的的方式不同。

请考虑这个场景,当你开始在一个专有的分支开发新的功能时,另一位团队成员更新了main分支的内容。这将会造成一个分叉的提交历史:
在这里插入图片描述
现在假设main分支内新增的内容与你正在开发的新功能有关。为了把main分支里新增的代码应用在你的feature分支,你有两种方法:merge 和 rebase。

  1. 使用merge

    # 切换到master,同步远程的最新代码
    git checkout master
    git pull
    
    # 把本地最新的master同步到分支上
    git checkout feature 
    git merge master
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这会在feature分支上创建一个合并分支,这次提交会连接两个分支的提交历史,在分支图示中结构像这样:
    在这里插入图片描述
    合作操作友好,因为没有破坏性,现存分支历史不会发生什么改变,但另一方面,意味着每当feature分支需要应用上游分支的更改时,都会在提交历史中增加一个无关的提交历史。 如果master分支更新很活跃(多人开发中确实活跃), 这种操作对功能分支的提交历史产生相当程度的污染,这是这个命令的弊端。

  2. 使用rebase
    为了替代merge操作,也可以把feature分支的提交历史rebase到master分支的提交历史顶端(重新定基):

    # 切换到master,同步远程的最新代码
    git checkout master
    git pull
    
    # 把本地最新的master同步到分支上
    git checkout feature 
    git rebase master
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这个操作会把feature分支的起始历史放到master分支的最后一次提交上,也达成了使用master分支中新代码的目的(也就是相当于新的feature相当于在最新的master上出来的,变基了一下)。但,相对于merge操作中新建一个合并分支,rebase操作会通过为原始分支的每次提交创建全新的提交,从而重新原始分支的提交历史。
    在这里插入图片描述
    使用rebase操作的最大好处在于你可以让项目提交历史变得非常干净整洁。首先,它消除了git merge操作所需创建的没有必要的合并提交。其次,正如上图所示,rebase会造就一个线性的项目提交历史——也就是说你可以从feature分支的顶部开始向下查找到分支的起始点,而不会碰到任何历史分叉。

    But, rebase操作丢失了合并提交能够提供的上下文信息——所以你就无法知道功能分支是什么时候应用了上游分支的变更。

  3. 可交互式rebase
    可交互式rebase让你在把变更提交给其他分支之前有机会对提交记录进行修改。这甚至比自动rebase操作更强大,毕竟它提供了对于分支提交历史的完全掌控力。通常来说这一操作的使用场景在于合并功能分支到main分支之前,对于功能分支杂乱的提交记录进行整理
    进行可交互式rebase操作, 需要向git rebase命令传递-i参数

    git checkout feature
    git rebase -i master
    
    • 1
    • 2

    执行以上命令会打开一个文本编辑器,其中内容为分支中需要移动的所有提交列表:

    pick 33d5b7a Message for commit #1
    pick 9480b3d Message for commit #2
    pick 5c67e61 Message for commit #3
    
    • 1
    • 2
    • 3

    上面这样的列表正表示了分支被rebase之后其历史的长相。通过修改pick命令或者对提交历史进行重新排序,你可以让最终的提交历史变成任何你希望的样子。比如说,如果第二次提交修复了第一次提交的什么BUG,你可以使用fixup命令替代pick来把两次提交压缩在一起。

    pick 33d5b7a Message for commit #1
    fixup 9480b3d Message for commit #2
    pick 5c67e61 Message for commit #3
    
    • 1
    • 2
    • 3

    当你保存并关闭这个文件之后,Git会根据你的调改结果执行rebase操作,根据上面的例子项目历史会变成下图这样:
    在这里插入图片描述
    通过清除那些并不重要的提交历史可以让项目整体的历史更易读易懂。这一点是git merge操作所无法提供的。

    关于rebase的使用详细资料,可以参考这篇文档

7. git版本回退

git版本回退的意思是假设我修改了几版代码,提交到了远程仓库, 但是呢? 发现新提交的代码有错误, 我想回退到某个之前指定的版本,或者是在开发过程中遇到合并别人的代码或者主分支代码导致了自己分支代码冲突有问题等, 这时候都需要回退到某个git提交历史的代码,此时就需要用到git reset命令。

# 先查看下提交日志, 知道要回退到哪个版本
git log
# 这里会列出提交的每次记录以及版本号,这是一个哈希值
  • 1
  • 2
  • 3

like this:
在这里插入图片描述

# 根据之前提交的描述,进行版本回退
git reset --hard 回退的版本号
  • 1
  • 2

结果:
在这里插入图片描述
此时本地仓库的HEAD指向了之前的某个版本, 但是远程仓库上还是最新的版本,所以如果想把本地这个之前的版本推到远程,直接git push会报错(版本要旧),需要强制推

# 这里要先注意在自己分支上
git push -f
  • 1
  • 2

既然谈到了版本回退, 就要整理下git reset和git revert的区别了,随着在工作中用git的次数越来越多,也渐渐的有了自己的理解。

  • git reset: 用于回退版本, 会遗弃不再使用的提交。
    在这里插入图片描述
    比如, 从版本B, 作了一些修改, 到了版本C, 然后再做修改,得到版本D, 此时HEAD在D上, 这时候,假设我们git reset HEAD^^, 此时HEAD就重新回到B, 新作的两次修改就会被丢弃掉(注意,这里说的是本地暂存区, 不涉及远程仓库),具体使用:

    // 没有指定ID, 默认使用HEAD, 暂存区的内容会被当前ID版本号的内容覆盖,工作区不变 
    git reset 
     
    // 指定ID,暂存区的内容会被指定ID版本号的内容覆盖,工作区不变 
    git reset <ID> 
    // 提交到远程,由于git reset回退,本地代码落后远程,于是需要-f强推
    git push -f origin branch 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    常见选项:

    • --mixed(默认):默认的时候,只有暂存区变化, 暂存区回到了之前的版本, 此时如果要这个修改,需要git add
      在这里插入图片描述

    • --hard参数:如果使用 --hard 参数,暂存区,工作区都会被修改,且无法找回。

    • --soft:如果使用 --soft 参数,仅仅会重置HEAD到制定版本, 不会修改暂存区和工作区, 工作区内容没变, index有最近一次提交的修改, 无须git add。
      在这里插入图片描述

    这玩意使用的时候,一定要想清楚是否要回退到的版本之后的新修改都不要了,还是只想丢弃某次修改。 如果只想丢弃中间的某次修改,后面的还要保留,需要用下面这个。

  • git revert: 撤销某次操作,和git reset产生的效果一样,但是, git revert不是丢弃已经修改的commit, 而是从当前基础上,产生一次新的版本,而这个版本,和想回退到的版本是一样的。
    在这里插入图片描述
    比如, 在分支B 上作了一些改动,得到了版本C, 此时假设再用B, git reset的话,就直接丢弃C, 回到B,而git revert是从C 基础产生一个新的版本B’, 这个B’是和B一样的, 相当于从C作了去除了B->C的改动得到了新版本B’。

    // 撤销任意
    git revert <commit_id> 
    // 撤销一个版本
    git revert HEAD
    // 撤销前前版本 
    git revert HEAD^ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

git revert 和 git reset的区别

  1. git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit。
  2. 在回滚这一操作上看,效果差不多。但是在日后继续merge以前的老版本时有区别。因为git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch时,导致这部分改变不会再次出现,但是git reset是之间把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit应该还会被引入。
  3. git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。

如果回退分支的代码以后还需要的情况则使用git revert, 如果分支是提错了没用的并且不想让别人发现这些错误代码,则使用git reset

8. git amend

这个在工作中遇到的场景是这样, 在分支上修改完一版代码, 通过git add -> git commit -m "xxx" -> git push系列操作提交到远程,结果到远程之后, git commit -m后面的注释格式错误,公司里都有代码开发规范的,我这次提交的时候,没有按照那个规范写,所以远程那边报错误了。

所以,我需要重新修改git commit -m xxx的内容,重新git push, 但是直接这样写肯定是不行, 这样就成了两次提交,也不确定可不可行,所以,mentor说用--amend命令追加下提交内容,覆盖掉原来的就好。操作步骤如下:

git commit -m --amend "新的注释内容"
git push -f   # 注意在当前的分支上
  • 1
  • 2

这样就解决问题了。

9. git命令常用别名

这个在.git/config进行配置

[alias]
        co = checkout
        br = branch
        ci = commit
        st = status
        unstage = reset HEAD --
        last = log -1 HEAD
        pr = pull --rebase
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

10. git stash

这个命令的使用场景是这样, 假设我在A分支上进行任务开发, 修改了很多个文件,开发到一半之后, 需要切换到B分支上去看一些别的事情, 此时如果直接切换, 会提示当前A分支和远程的A分支已经不一样, 需要先把冲突处理了再去切换。

此时, 有两种解决方法:

  1. 第一种就是在当前A分支上, git add 然后 git commit, 相当于把A分支上的修改保存了起来,然后再去切
  2. 另一种方式是在当前A分支上, 输入git stash, 这个也是相当于把A分支上的修改存储到了一个栈里面, 看到的是没改之后的代码了, 这时候再去切到B分支,如果再从B分支切到A分支上来, 使用命令git stash pop,就能看到A分支上修改后的代码,然后在这个基础上接着开发。

相比较于第一种方法, git stash操作更加灵活一些,不用先提交进去。

11. git 提交记录合并

工作之后, 发现有了更多git使用的新问题,提交代码的时候, 可能面临着会产生多次提交记录的情况,比如提交了一版代码,突然发现,有个bug, 就从本地修改,又重新git add commit push了一次。 每次走这3个步骤的时候,其实后面都产生了一次新的提交记录, 如果提交修改次数太多, 这时候,我们git log一下, 就会发现,近几个提交记录,全是修改了什么什么bug, 使提交变得零乱,都不知道当时是开发了什么功能。

我首次提交代码的时候,就犯了上面的这个问题, 然后metor说,你提交记录太多了,把这些bug的合并起来吧, 最终保留一个提交记录。 What? 这是什么鬼? 怎么合并?

下面整理两个实践方法:

  1. 如果是提交完了的代码出现了bug, 我们本地修改之后, 此时不要git commit, 而是可以用上面整理的

    git commit --amend -m "注释"
    # 或者
    git commit --amend --no-edit   # 直接用上次注释
    
    • 1
    • 2
    • 3

    这样就不会产生新的提交记录了。

  2. 上面这个是如何避免不产生多次提交记录, 那么如果已经产生了多次提交记录,就比如我上面的,此时就需要进行提交记录合并了, 这时候用到了伟大的rebase交互

    # 首先 git log查看提交日志
    git log
    
    # 然后, 看看想把哪些提交记录进行合并, 找到要合并的最后一个节点的下一个节点的git log id
    git rebase -i 那个log id  # 注意此时的这个log 是不参与合并的
    
    # 此时会打开一个交互式窗口, 从上到下,是时间线从早到晚, 最上面的第一行,就是上面这个log提交记录,开头pick保持不变
    # 下面需要合并的那些提交记录, 前面的pick换成s, 表示压缩成一个
    # 然后
    git push -f
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    所以rebase命令还是很强大的。

12. git 删除无用的分支

git上在分支上开发完代码, 及时提merge request合并到master, 否则时间一长, 这个分支就会落后于master很多,就需要重新rebase,所以及时合并,并且合并完之后,及时清理掉这个分支,这样才不会因为维护的分支过多,而太乱, 反正已经合并到master,下次开发的时候, 再从master重新切出分支即可,下面整理删除分支的命令:

# 删除远程分支
git push origin --delete 远程分支名

# 删除本地分支
git branch -d 本地分支名
  • 1
  • 2
  • 3
  • 4
  • 5

这里再整理一个往master合并的小技巧, 如果是一个落后master很多的分支要合并,一般需要先重新rebase 到master,然后才能合并进去,即先

git checkout master
git pull
git checkout 需要rebase的分支
git rebase -i master

# 此时可能会有文件冲突, 解决冲突的文件,然后git rebase --continue
# 如果显示成功变基到master, 说明rebase完成
# 此时git push -f就能更新远程的分支, 但此时,可能这个分支上已经有了很多次提交记录
# 为了保持合并分支的提交记录整洁, 这里的一个小技巧是
# 在rebase之后分支的基础上,重新切出一个新的分支, 然后把这个分支合并到master
git checkout -b dev-new
git add .
git commit -m ""
git push origin dev-new

# 在dev-new上提mr请求,此时就能保证只有一次提交了
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

另外记录一个点,就是master分支上的代码如果出现bug了,如何快速的修复? 注意, 一般公司里面master分支上是不允许直接提交代码的,此时,修复的流程:

# 基于现有的master分支,先切一个新的bug分支
git checkout master
git pull
git checkout -b dev-bug

# 在dev-bug上修复bug文件,然后重新提交mr进行合并到Master
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

13. Git Tag

git tag, 我理解,类似于版本控制系统,给仓库中某一个历史提交打上标签,来标记某个版本的重要性。最近要使用这个功能来标记项目的发布节点v1.0, v2.0等。

背景: 上面提到,我们开发完一个项目之后,想要上线, 此时必须要提供能运行我们项目的一个镜像才行,常见的操作,就是会把我们测试代码通过的这个容器打包成一个镜像,然后上传云端,部署项目上线的时候,直接拉取这个镜像。

但构建镜像的过程很繁琐,公司提供了一个自动化的流程,就是代码要发版上线的时候,只要给提交打上tag, 此时会自动触发构建镜像的流程,自动创建好,只需要拉取运行即可(前提,项目里面事先编写好docker file)。

所以基于这样的一个背景,学习了下如何给某次提交打上tag,来触发这个自动构建镜像的流程。

这个操作,顺便把线上的代码固化下来,因为构建的这个镜像,只能运行当前这一版代码,如果修改代码,那相当于是一个新的版本,需要重新打tag构建镜像,所以这个操作一般用于线上版本发布,也就是项目稳定,普通测试肯定不能这样玩。

常用命令如下:

# 列出当前所有标签
git tag -l [| grep]

# 在分支创建标签或者master上创建,由于我这个是测试,直接在分支上创建的
git tag tag-test-v1.0.0 -m "tag -test"
# 也可以给历史某个提交版本打标签
git tag tag-test-v1.0.0 -m "tag test" commit_id

# 查看
git show tag-test-v1.0.0

# 推送到远程
git push origin tag-test-v1.0.0

# 删除标签
# 本地
git tag -d tag-test-v1.0.0
# 远程
git push -d origin tag-test-v1.0.0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

参考资料

下面贴一个适合随时随查的教程了, 粗略的过了下,写的很详细,非常适合用的时候查:

但有些我目前没有用到,所以理解起来就有些困难,我发现,这东西,当真正用到的时候,才是学起来比较快的时候, 才真正的有印象。 像上面这个分支的这里, 之前怎么看都感觉不理解,结果真正用的时候, 一晚上就有感觉了,所以学习知识,真的要想办法学以致用 本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/440679

推荐阅读
相关标签