您现在的位置是:首页 >技术交流 >我记不住的那些Git的操作网站首页技术交流

我记不住的那些Git的操作

Penguinbupt 2023-07-17 00:00:04
简介我记不住的那些Git的操作

背景:其实接触Git也很长时间了,自打上学那会就用Git作为版本控制工具,感触颇深。写这篇文章也是记录一下自己的理解留作日后词典进行查询,另外也是想把这些内容分享给大家。本篇将以问题为导向来阐述相关的知识,面对的对象为具有一定经验的开发者。

假设当前项目有两个分支,为master和dev,所有开发工作都在dev上进行,而master分支为用于发布生产代码的分支

我整理了我在日常工作中的十个问题,重点是第4个问题和第8个问题,如下所示:

1.撤销本地工作目录中的更改

git checkout -- <file>

这样将撤销对本地工作目录的更改,此操作与修改<file>是相反的操作。

此操作不会移动HEAD指向,这里的 “ -- ”其实就是代表的是HEAD

checkout 操作也可以跟 路径或文件如下图所示:

2.撤销本地缓存的更改

Reset With a Path

当reset 指令后面是某个文件或路径,则不会改变分支的指向(skip),只会影响缓存区和工作区的内容,如下图所示:

 注意: git reset --mixed HEAD file.txt  与  git reset file.txt 是等价的

             因为 --mixed是默认的策略,HEAD也是默认的指向值。

1.
//从缓存区下台这个文件,但不改变工作目录的内容,与git add <file>是反义词
git reset --mixed HEAD <file>      
或
git reset <file>  



2.
//从缓存区移除所有已加入的文件的缓存,而不会覆盖任何修改,与git add .是反义词
git reset              
或
git reset HEAD


3.
//从缓存区移除所有已加入的文件的缓存,并且恢复工作目录
git reset --hard
或
git reset --hard HEAD           

有三种选择:

--soft        只改HEAD指针的指向,不修改任何 缓存区和工作目录的内容

--mixed    默认,将改HEAD指针的指向,也将缓存区重置,但不改变工作目录的内容

--hard      改变HEAD指针的指向,缓存区重置,工作目录重置

3.当在本地提交commit后如何修改这个commit message?

git commit命令有一个amend参数,用于修改之前的提交信息

git commit --amend

当点击回车后,会出现一个编辑框,重新编辑内容并保存退出即可。

其实还有一个场景是:你写的commit message是对的,但是你忘记了修改仓库中某个文件的内容,那怎么办?

这时候你有两个方法,第一就是重新修改然后add和commit,即生成一个新的节点,后续也可以rebase解决。

第二种就是在当前这个节点上修改然后add,最后amend,即在原来的节点进行修改。

vim  test.txt
​
git add . 
​
git commit --amend

这是一种将忘记的修改添加到当前这个节点的方法

总结:amend这个参数不仅仅能修改commit message,还能对仓库中的文件再次进行更新和修改

4.当周三升级要对某个版本进行打包

首先通过git log命令查询当前的历史,例如:

commit ae4fa4a6d8f9b4f6095c822935e3e0f7ab20f7cd (HEAD -> master)
Author: lsqtongxin <lsqtongxin@qq.com>
Date:   Sat Jun 19 11:09:06 2021 +0800
​
    add third.java
​
commit 1cf533f4bca614a163810da46657efc9343075d5
Author: lsqtongxin <lsqtongxin@qq.com>
Date:   Sat Jun 19 11:08:18 2021 +0800
​
    add second.java
​
commit 9d69109d65ffd13291c3f72f304e36a20b99b32b
Author: lsqtongxin <lsqtongxin@qq.com>
Date:   Sat Jun 19 11:06:48 2021 +0800
​
    add main.java

当你想使用second.java(1cf533f)来进行周三生产升级,但是当前的最新的节点为third.java(ae4fa4a)它是你最近完成的代码内容,即你电脑硬盘里显示为third.java版本。那你如何操作呢?

使用git checkout 命令来针对某个版本进行检出代码:

git checkout 1cf533f                  //这样你的硬盘将会恢复为second.java文件等

然后进行代码的打包、编译、测试即可,上传并升级即可。

又有人问,我第二天上班时候,如何恢复到最新的状态呢?

通过git log是没法找到third.java的commitID的,那么如何找到third.java的commitID呢?

假设我们刚刚是在master上进行操作,所以最新的third.java节点位于master分支上。

git checkout master                    //这样将会使恢复如初。

总结: git checkout 本质上是通过改变HEAD的指向来进行移动节点,在多分支操作中,这个命令还用于切换分支

5. 开发某个代码时想看一下之前的版本中某个文件

此操作不会移动HEAD指向

接上面的第4步骤中的git log,例如:

git checkout <commit> <file>

查看文件之前的版本。

注意: 它将工作区中的某个文件的内容 变成指定的commitID的某个文件内容,同时缓冲区也会被修改,也就是说 你在工作区 修改<file>,然后执行这个操作,你原来的修改将不会被保存而是被commitID的文件内容进行覆盖。

那么如何返回最新的版本的file呢?

git chekcout HEAD <file>

这个命令也就是说 只能在没有任意修改的时候,进行切换来查看文件内容,否则将被覆盖。

具体比较如下图所示:

 WD safe 代表 是否 working-directory safe ?

6.合并你的多个提交(压缩提交)

假设你在dev分支上,新建一个feature分支开发一个功能点,计划5个工作日完成,你为了不丢失每天的工作内容,每天在本地commit一个提交来记录你当天的工作,那么你就有了5个commitID,导致你后续会因为开发很多功能点会有很多个commitID,有的功能点需要10个工作日即10个commitID,你会发现这些commit非常繁杂。

那么我要是按照功能点的颗粒度,是否可以将这5个commitID或者10个commitID合并为一个commitID来呢?

这样会将你的历史很简洁、干净和清爽,翻阅过往的历史也会很快速。并且会使你的log保持清晰,简化整体commit数量,非常的实用。

git rebase -i <base>                //在feature分支上

其中为一个基准点,为某一个commitID,都是以这个基准点进行合并,但是合并的内容不包括这个基准点。

git rebase -i cf375ac               //在feature分支上

假设我们的历史从古至今为:25ccabd->0134238->d46d81e,也就是合并这三个节点为一个节点。

25ccabd为feature的第一天工作

0134238为feature的第二天工作

d46d81e为feature的第三天工作

而这个基准点为cf375ac,这个commitID cf375ac内容等等均不会变化。这里一定注意参数这不是25ccabd,然后将0134238和d46d81e前面文字由pick改为squash或者s,保存退出,然后再重新写提交信息,最后保存退出即可。

7.拉取更新

先 fetch,然后 merge。git pull 命令是整合了这两个过程的方式。

git fetch                            //从远程拉去默认主机origin的所有分支
git fetch <remote>                   //从远程拉去remote这个主机的所有分支
git fetch <remote> <branch>          //从远程remote拉取某个分支的更新

git remote                           //查看所有的远程主机

例如:

git fetch origin dev                 //拉取远程origin/dev分支的更新
​
git branch -r                        //查看远程分支
​
git checkout dev                     //切换到dev分支
​
git merge origin/dev                 //将远程origin/dev合并到本地dev分支上

于是我们得到了远程origin/dev的更新,将其他同事的commit更新到了我的本地。

git pull是上面两个过程的整合,可以参考第8步。

8.分支合并

假设我们基于dev分支开发某一个feature功能点:

git branch feature dev              //基于dev新建一个feature分支
git checkout feature                //切换到feature分支进行开发工作

这时候你就可以专注于你的工作,vim sample.txt / git add . /git commit -m "revise sample file"等

最后你完成了你的feature开发。

当多人协作时候,有许多人都合并了他的某个分支到dev分支上,导致dev分支有很多更新。

那么当我们完成了我们的feature功能后,我们如何操作呢?

首先我们应该远程拉取dev分支的更新:

git checkout dev                     //切换到dev分支
git pull origin                      //拉取远程origin的dev分支的更新

如果本地dev已经提交了更新,那么需要合并本地dev和远程dev:git pull --rebase origin

当从远处origin dev更新完毕,即为(startTime)

然后在feature分支上进行rebase操作:

git rebase -i dev                   //这一步类似第6步骤

这一步rebase包含了两个方面的功能,1.以最新的dev为基   2.根据最新的dev进行合并多个节点。

最后切换到dev分支进行合并:

git checkout dev
git merge feature

其实这一步git merge是快速前进(Fast forward模式)

再进行将dev分支推送到远程主机(endTime)

git push origin dev

这一步有可能失败,是因为在startTime到endTime这一段时间又有人提交更新,即你更新的时间到你提交的这段时间又有人提交,导致你的节点落后。

git pull --rebase origin
git push origin dev

这个 --rebase,就是会使用git merge替换为git rebase,即实现了git fetch和git rebase两条指令。

最后删除分支:

git branch -d feature

总结:

整体步骤分为

第一创建分支:根据业务需求在dev上创建你自己的本地分支feature

第二编写代码:在feature分支上进行编写,并产生了多个提交节点。

第三pull:先拉取远程dev的更新,

第四rebase:再基于dev进行 rebase,

第五merge,最后将feature合并到dev分支。

第六是push

第七是删除feature分支

9.撤销某次commit的更改

git revert <commitID>

这个命令的重点会再生成一个新的节点,并且不会删除这个旧的节点,这样避免了丢失项目历史。

一般用于当某个历史提交引入了bug,要么是将那个引入bug的节点revert退回,要么就是直接建立fixbug分支来解决bug再进行合并等。

10.删除某次commitID到最新节点的更改

git reset 这个命令用于改变当前分支所指向的commitID,而不是改变HEAD的指向,因为HEAD一般指向分支,如下所示:

HEAD --->>> master --->>> commitID

 详细可参考 Git HEAD及detached headGit - Reset Demystified

假设:从古至今  V1->V2->V3

git reset 有三种选择:

--soft        只改分支的指向,不修改任何 缓存区和工作目录的内容,也就是说 缓存区和工作区都保还继续保持最新的节点的内容,一般不用这个选项

例如:git reset --soft V2   //此时 HEAD指向分支,分支指向V2,缓存区和工作区都还是V3

--mixed    默认,将改分支的指向,也将缓存区重置,但不改变工作目录的内容,也就是说 缓存区被改为commitID节点的内容,而工作目录还是保持最新节点的内容。

 例如:git reset --mixed V2   //此时 HEAD指向分支,分支指向V2,缓存区是V2,工作区都还是V3

--hard      改变分支的指向,缓存区重置,工作目录重置,也就是说缓存区和工作区都被改为commitID节点的内容。

 例如:git reset --hard V2   //此时 HEAD指向分支,分支指向V2,缓存区是V2,工作区是V2

10.1 删除某次commitID到目前的更改,且保存从commitID到目前节点的工作目录中各文件的内容的修改:

git reset <commit>      //也可以是 HEAD^  默认是mixed

10.2 删除某次commitID到目前的更改,不保存从commitID到目前节点的工作目录中各文件的内容的修改:

git reset --hard <commit>
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。