在工作以及日常的代码管理中,都需要使用到git技术,本文简要介绍了git并图示了主要的git命令
如果您需要更多git命令以及git相关知识,可以访问一下网址:
出色的git学习网站
CS-Notes
git完整命令手册
新建一个仓库之后,当前目录就成为了工作区,工作区下有一个隐藏目录.git,它属于Git的版本库。
Git的版本库有一个被称为Stage的暂存区以及最后的History版本库,History存储所有分支信息,使用一个HEAD指针指向当前分支。
git add files将文件的修改添加到暂存区
git commit将暂存区的修改添加到当前分支,提交之后暂存区就被清空了
git reset – files使用当前分支上的修改覆盖暂存区,用来撤销最后一次git add files
git checkout --files 使用暂存区的修改覆盖工作目录,用来撤销本地修改
可以跳过暂存区域直接从分支中取出修改
git commit -a直接把所有文件的修改添加到暂存区然后执行提交
git checkout HEAD --files 去除最后一次修改,可以用来进行回滚操作
使用指针将每个提交连接成一条时间线,HEAD指针指向当前分支指针。
新建分支是新建一个指针指向时间线的最后一个节点,并让HEAD指针指向新分支,表示新分支成为当前分支。
每次提交只会让当前分支指针向前移动,而其他分支指针不会移动
合并分支也只需要改变指针即可。
忽略以下文件:
操作系统自动生成的文件,比如缩略图
编译生成的中间文件,比如Java编译产生的.class文件
自己的敏感信息,比如存放口令的配置文件
新建一个名为newImage的分支
git branch newImage
但是目前我们只是新建了一个分支,没有切换到该分支上,使用命令切换到该newImage分支上
git checkout newImage
有一种更简洁的方式,可以使用
git checkout -b
来实现创建一个新分支同时切换到新创建的分支
将merge的分支合并到当前分支里,例如当前分支为bugFix,
git merge main
就是将main分支合并到bugFix分支
rebase实际上就是取出一系列的提交记录,“复制”它们,然后再另一个地方逐个的放下去。
原始状态为
之后运行:
git rebase main
注意提交记录c3依然存在,而c3‘是我们rebase到main分支上的c3
的副本。
tag可以永久的将某个特定的提交命名为里程碑,然后就可以像分支一样引用了。
更难得的是,它们并不会随着新的提交而移动。你也不能切换到某个标签上面进行修改提交,它就像提交树上的一个锚点,标识了某个特定的位置。
git tag v1 c1 //将标签命名为v1,并且明确让它指向提交记录c1,
//如果不指定提交记录,git会用HEAD所指向的位置
由于标签在代码库中起着“锚点”的作用,Git为此专门设计了一个命令来描述离你最近的锚点,就是git describe
git describe的语法是:
git describe
可以是任何能被git识别成提交记录的引用,如果你没有指定的话,git会以你目前所检出的位置(HEAD)
它输出的结果是这样的:
__g
tag表示的是离ref最近的标签,numCommits是表示这个ref与tag相差有多少个提交记录,hash表示的是所给定的ref所表示的提交记录哈希值的前几位。当ref提交记录上有某个标签时,则只输出标签名称。
HEAD是一个对当前检出记录的符号引用,也就是指向你正在其基础上进行工作的提交记录。
HEAD总是指向当前分支上最近的一次提交记录。大多数修改提交树的git命令都是从改变HEAD的指向开始的。
HEAD通常情况下是指向分支名的(如bugFix)。在你提交时,改变了bugFix的状态,这一变化通过HEAD变得可见。
分离的HEAD就是让其指向了某个具体的提交记录而不是分支名。
git checkout c1
通过哈希值指定提交记录很不方便,所以Git引入了相对引用
使用相对引用可以从一个易于记忆的地方(比如bugFix分支或HEAD)开始计算。
使用^向上移动1个提交记录
使用
我们使用相对引用最多的就是移动分支。可以直接使用-f选项让分支指向另一个提交,例如:
git branch -f main HEAD~3
上面的命令会将main分支强制指向HEAD的第三级父提交。
和提交一样,撤销变更由底层部分(暂存区的独立文件或者片段)和上层部分(变更到底是通过哪种方式被撤销的)组成。我们更关注后者。
主要有两种方法用来撤销变更,是git reset还有git revert
git reset 通过将分支记录回退几个提交记录来实现撤销改动。git reset向上移动分支,原来指向的提交记录就跟从来没有提交过一样。
执行如下命令:
git reset HEAD~1
之后为:
Git将main分支移向c1;现在我们本地代码库根本不知道有c2这个提交了(在reset后,c2所做的变更还在,但是处于未加入暂存区的状态。)
虽然在本地分支中使用git reset很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的。为了撤销更改并分享给别人,我们需要使用git revert。
使用命令:
git revert HEAD
在我们要撤销的提交记录后面多了一个新提交。这是因为新提交记录c2’引入了更改,这些更改刚好是用来撤销c2这个提交的。也就是说c2‘的状态与c1是相同的。
revert之后就可以把你的更改推送到远程仓库与别人共享
本系列的第一个命令是
git cherry-pick <提交号>
如果你想将一些提交复制到当前所在位置(HEAD)下面的话,cherry-pick是最直接的方式了
我们想将side分支上的工作复制到main分支上。
git cherry-pick c2 c4
当你知道你所需要的提交记录(并且还知道这些提交记录的哈希值)时,用cherry-pick再好不过。但是如果你不清楚你想要的提交记录的哈希值时,我们可以利用交互式的rebase。如果你想从一系列的提交记录中找到想要的记录。
交互式rebase指的是使用带参数–interactive的rebase命令,简写为-i。
当rebase UI界面打开时,你能做三件事:
调整提交记录的顺序(通过鼠标拖放来完成)
删除你不想要的提交(通过切换pick的状态来完成,关闭就意味着你不想要这个提交记录)
合并提交
git会按照UI中你的操作,原本复制副本。
git clone之后在我们的本地仓库多了一个名为origin/main的分支,这种类型的分支叫做远程分支
远程分支反映了远程仓库(在你上次和它通信时)的状态。
远程分支有一个特别的属性,在你检出时自动进入分离HEAD状态。Git这么做是出于不能直接在这些分支上进行操作的原因,你必须在别的地方完成你的工作,(更新了远程分支之后)再用远程分享你的工作成果。
我们从远程仓库获取数据,用git fetch
当我们从远程仓库获取数据时,远程分支也会更新以反映最新的远程仓库。
获取之前提交记录状态如图:
我们之后运行命令:
git fetch
可以看到c2,c3被下载到了本地仓库,同时远程分支origin/main也被更新。git fetch实际上将本地仓库中的远程分支更新为了远程仓库相应分支最新的状态。
git fetch并不会改变你本地仓库的状态。它不会更新你的main分支,也不会修改你磁盘上的文件。
既然我们已经知道了如何用git fetch获取远程的数据,现在我们学习如何将这些变化更新到我们的工作当中。
当远程分支有新的提交时,你可以像合并本地分支那样来合并远程分支,也就是以下命令:
事实上,由于先抓取更新再合并到本地分支这个流程很常见,因此Git提供了专门的命令,就是git pull
git push负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录。
在大型项目中开发人员通常会在(从main上分出来的)特性分支上工作,工作完成后只做一次集成。但是有些开发人员只在main上做push,pull,这样的话main总是最新的,始终与远程分支(o/main)保持一致。
对于接下来这个工作流,我们集成了两个步骤:
将特性分支集成到main上
推送并更新远程分支
初始状态为:
执行命令:
git pull --rebase;git push
首先将我们的工作rebase到远程分支的最新提交记录
向远程仓库推送我们的工作。
git通过当前检出分支的属性来确定远程仓库以及要push的目的地的,我们可以为push指定参数,语法为:
git push
git push origin main
切到本地仓库的“main”分支,获取所有的提交,再到远程仓库“origin”中找到“main”分支,将远程仓库中没有的提交记录都添加上去。
要同时为源和目的地指定的话,只需要用:将两者连起来就可以了:
git push :
4)]
首先将我们的工作rebase到远程分支的最新提交记录
向远程仓库推送我们的工作。
git通过当前检出分支的属性来确定远程仓库以及要push的目的地的,我们可以为push指定参数,语法为:
git push
git push origin main
切到本地仓库的“main”分支,获取所有的提交,再到远程仓库“origin”中找到“main”分支,将远程仓库中没有的提交记录都添加上去。
要同时为源和目的地指定的话,只需要用:将两者连起来就可以了:
git push :