本地版本控制
记录文件的每次更新,适合个人使用,例如RCS
集中版本控制
分布式版本控制 例如Git
在git官网下载安装包
或者淘宝镜像:CNPM Binaries Mirror (npmmirror.com)
下载最新的稳定版即可,本篇博客下载的是Git-2.37.0-64-bit
无脑下一步即可
需要注意的是:选择自己用的编辑器(这会涉及到我们后面使用某些命令打开git中的某些文件。选择自己常用来代替笔记本的编辑器即可,或者选择自己常用的编辑器)。vim一般用在linux,window看自己用的是什么就选什么,例如notepad++或者vs code,接着就是一路next即可。(这里我选择的是NotePad++
)
安装成功之后你可以在window菜单或者鼠标右键找到git,如图。
Git Bash:Linux命令行风格,使用最多
Git CMD:Windows风格命令行,和linux命令不同
Git GUI:图形化界面,不推荐初学者使用
这里我们使用Git Bash
cd:改变目录
cd …:回退到上一个目录,直接cd进入默认目录(这里需要和windows的cd区别,cd和…之间必须使用空格隔开,否则命令不识别)
pwd:显示当前所在的目录路径
ls(ll):列出当前目录中的所有文件,ll 列出的文件信息更加详细
touch:新建一个文件 如 touch index.js
就会在当前目录下新建一个index.js 的文件
rm:删除一个文件 rm index.js
就会把index.js删除
mkdir:新建一个目录,就是新建一个文件夹
rm -r:删除一个文件夹,rm -r src
删除src文件夹
rm -rf / 请勿尝试!这个的意思是递归的删除电脑上的所有文件
mv:移动文件 mv index.html src
index.html是我们要移动的文件,src是目标文件夹,这样写必须保证文件和文件夹在同一目录下
reset:初始化终端 \ 清屏
clear:清屏
history:查看命令历史
help:查看帮助
exit:退出
#:表示注释
初次使用Git需要我们设本机的用户名和邮箱,为之后的代码提交做身份区别(要知道该次提交者的身份)。
初次安装一般通过这种方式来配置我们的用户名和邮箱。
在任意位置右击鼠标右键选择Git Bash Here
,打开终端之后键入如下命令之后,Git会在相应的目录创建用户配置文件,用来存放我们的配置。
git config --global user.name "zhongz" #配置用户名
git config --global user.email [email protected] #配置邮箱
之后可以使用命令来查看我们的Git配置
查看全部配置git config -l
查看系统配置git config --system --list
查看用户配置git config --global --list
修改用户名和邮箱可以直接通过修改配置文件来实现。存在两种修改方式:
直接在git中使用命令打开配置文件(会通过你刚刚安装设置好的默认编辑器来打开配置文件)
git config --system -e
打开系统配置文件
git config --global -e
打开用户配置文件
通过路径找到文件
X:\XX\Git\etc\gitconfig
X代表你安装的Git目录,git安装目录下的config,这里可以找到系统配置文件,这里存在一些全局配置,初学不需要我们去改动
C:\Users\administrator \ .gitconfig
当前登陆用户的用户配置文件,如果初次安装是找不到这个文件的,需要使用Git Bash创建(或者手动创建一个),这个文件可以用来便于我们后期修改用户名和邮箱
关于git的环境变量:安装git之后,git会自动配置环境变量,不需要我们自己手动去配置
Git基本理论必须了解,重要但不太重要。因为以后工作中常用的反反复复总是几个命令。
Git本地有三个工作区:工作目录(Working Directory)、暂存区(Stage/Index)、资源库(Repository或Git Directory)。加上远程git仓库(Remote Directory)一共四个工作区。存在如下转换关系:
补充一些名词:
- master(Main):主分支
git add .
这个的意思是添加所有文件git commit
git push
创建本地仓库的方式有两种
在当前目录打开git bash,使用git init
命令初始化一个本地仓库。这个目录需要是git管理的项目的根目录。
执行之后可以看到一个.git文件(这是一个隐藏文件夹)被创建。
将服务器上的项目根目录上的数据克隆一份到本地,使用git clone 这里写你需要克隆的仓库的url
git add
命令将状态转变为staged(暂存态)git rm
移出版本库,文件状态转变为Untracked(未跟踪)。git add
加入暂存区,状态变为Staged(暂存态)。或者使用git checkout
将库中的文件同步过来覆盖该文件,丢弃修改,状态变为Unmodify(未修改)。git commit
命令将暂存区的文件加入库。文件状态转变为Unmodify(未修改)。使用git reset HEAD 这里写需要取消暂存的文件名
将文件取消暂存,文件状态转变为Untracked(未跟踪)或Modified(已修改)。git status 这里写需要查看的文件名.文件类型 #查看文件的状态
git status #查看当前目录所有文件的状态
git add . #添加当前目录所有文件到暂存区
git commot -m "new file filename.txt" #将文件提交到本地仓库并且为本次提交注释信息
一般情况下,在项目提交的过程中。我们不需要提交一些配置文件或者是本地文件。例如使用idea的话,.idea这个idea的配置i文件是不需要提交到远程仓库的。又或者一些npm_moudles或者一些本地文件。
在springboot中默认有一个文件.gitignore
是用来配置git在add文件到暂存区的时候会忽略哪些文件类型。或者我们可以自己创建这个文件
.gitignore
的一些配置使用规则:#
:注释符号*
代表0或者多个字符,?
代表一个字符,方括号[abc]
代表可选字符范围,大括号{"string1","string2"}
代表可选字符串!
:非,代表将不会忽略后面的文件/
:如果在文件夹名前面,则代表匹配根目录下的文件夹名,其他路径下的同名文件夹将不受影响;如果在文件夹名后面,代表忽略该文件夹内的所有文件。#符号后面的内容将被注释
*.txt #忽略所有txt类型的文件
!lib.txt #不忽略lib.txt文件
/temp #忽略根目录下的temp文件夹
temp/ #忽略所有路径下的temp文件夹里的文件
doc/*.txt #忽略doc文件夹下的txt类型的所有文件
git熟悉之后可以使用gitlab搭建自己的git服务器(需要在Linux环境下搭建),一般而言公司都会有自己公司内部的git服务器。本博客使用gitee,注册登陆即可。注:gitee现在所有创建的仓库都默认私有不能公开,公开仓库需要提交至人工审核。推荐使用GitHub创建公开仓库,会更快更方便
设置本机绑定SSH公钥,实现免密码登陆,可以避免每次push到远程仓库的时候都要输入一次密码
ssh-keygen -t rsa
,执行之后会提示我们需要输入一些东西,不需要管,直接拍回车键即可。IDEA集成Git有多种办法,本博客使用其中一种。
在idea中创建项目的时候将项目的位置选为git已经初始化的文件夹下,然后将你克隆下来的项目的文件夹里面的所有东西剪贴到你刚刚创建的项目目录里,覆盖即可。
注意:如果你使用git克隆项目的时候需要输入你的用户名和密码(这里可能是因为gitee只能创建私有仓库的原因),那么你输入你gitee上的用户名和密码即可继续克隆;或者在gitee上复制仓库url的时候不使用https,而是选址ssh的url复制到命令(前提是你配置了公钥),这样就可以不用输入密码。
覆盖之后idea里没有变化的解决办法:
- 点击菜单栏里的VCS,选择import into version control,选择create git repository
- 在打开的选项卡中的路径选项中,选择我们刚刚创建项目的根路径即可
- 此时看到右上角git的三个按钮和左边项目文件列表里文件名出现颜色标识即代表可以在idea里使用git了
提交到本地仓库:点击右上角一个绿色的勾,在左侧文件列表会出现一个提交菜单,选择需要提交的文件即可。在提交菜单的右下角可以配置提交的选项,基本上可以把选项全部去掉之后再提交(这里 需要注意使用push命令提交到远程仓库里的时候需要gitee账号设置邮箱为公开,否则提交不上去)
如何添加到暂存区:打开的terminal,键入git命令即可。此时左边的文件列表里的文件颜色标识会变成绿色(代表文件被添加到暂存区)。单个文件添加可以在文件列表中右键该文件,找到git选项,点击add即可
主分支:一般叫做master或者main
#查看本地分支
git branck
#查看远程分支
git branck -r
#新建分支,但仍停留在当前分支
git branck 这里写新分支名称
#新建分支,并且切换到新的分支
git checkout -b 新分支名称
#合并指定分支当当前分支
git merge 这里写指定分支
#删除分支
git branch -d 需要删除的分支名称
#删除远程分支
git push origin --delete 分支名称
git branch -dr [branch/remote]
存在多个分支都修改了同一个文件的时候,提交代码的时候会发生冲突,这个时候就需要双方协商保留谁的代码,修改冲突文件之后重新提交
注意:master主分支应该要非常稳定,用来发布新的版本,一般情况下不会到master主分支上进行开发,一般会使用一个dev分支进行开发,等到开发结束dev分支稳定之后会合并到主分支
命令可以在这个git沙盒中尝试:Learn Git Branching (gitee.io)
git rebase 分支名称
:这条命令可以用来将当前分支合并到指定分支,但是和git merge
不同的是,rebase是直接将bugFix的分支直接合并到主分支。他会把当前分支的历史提交记录也合并到主分支上。将类似于多条分支的情况转变成一条分支,也就相当于顺序开发一样,历史提交记录会呈现一种线性的图形。
两种用法:
git rebase 分支名你
将当前分支合并到我们写的分支中,git rebase master side
将side分支合并到master分支中
git merge:命令使用git merge 分支名
将某一个分支合并提交到当前分支。
git commit -m "fix(hello.txt):change content"
:这条命令意思是将当前分支提交到本地仓库,并以参数的形式附上提交信息。这里推荐读者去了解git提交规范,在多人协作开发种一个好的规范能让开发者有更好的沟通效率。当然这并不是硬性要求。
git add .
:将工作区的所有文件添加到暂存区.
换成文件名+文件格式可以添加指定的文件到暂存区。
git branch 分支名
:创建一个新的分支,但不切换到新的分支,当前的工作分支没变。
git chekout -b 分支名
:创建一个新的分支,并切换过去。
git reset
:
--hard
参数撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交。--soft
参数用于回退到某个版本,一般后面会跟某个版本的哈希值或者相对引用。撤销变更有两条命令,git reset 回退版本的哈希值或者相对引用
和git revert 回退版本的哈希值或者相对引用
git reset
是重置的意思,当前版本回退到某个历史版本将会导致当前版本和历史版本之间的提交记录被git丢弃。也就是无法再次回到当前版本。在本地仓库中你可以使用这个命令,但是不要在远程仓库中使用该条命令。git revert
会产生一个新的提交记录,这个提交记录和你回到到的某个提交记录的内容是一样的。和git reset
不同的是,它不会重置历史版本,你任然可以回到到分支的任何一个版本上。跟推荐在远程仓库的分支上使用这条命令。reset像是改写历史,revert更像是重现历史。HEAD:这是一个指向,一般是指向最后一次提交记录的分支,当然我们也可以直接让他指向某个提交记录,使用git checkout 提交记录的唯一标识(一般是一个哈希值)
git log:查看日志,一般使用该命令可以查看到提交的历史记录,展示每一次提交的哈希值。
相对引用:正如上面所说的,使用
git checkout 某一次提交的哈希值
这种方式使用的哈希值太难记住了,而且每次切换都要查一遍git的日志来找到对应的哈希值。这太麻烦了,所以出现了相对引用,相对引用可以让我们不必使用全部的哈希值,而且改用哈希值的前几个字符来代表该次提交记录。并且出现了相对简便的方式。git checkout HEAD^
使用符号代表当前分支的最后一个提交记录向上移动一个提交记录,也就是C3’的提交记录往上HEAD指向C2。多次移动可以加多个或者使用~加上数字git checkout HEAD~4
。git checkout 分支名称^
可以移动到某个分支的上一个提交记录
移动分支:这可以让分支进行移动,git branch -f master HEAD~3
,让分支master移动到head上面的三级,那么下面的master没有指向的记录就不属于master分支了
git cherry-pick 提交记录哈希值或者相对引用
:可以将指定的提交记录复制一份放在当前分支下作为commit提交记录(可以写多个提交记录哈希值或者相对引用,git会一次性复制它们并按顺序作为提交记录)
交互式的rebase:指的就是rebase带有参数--interactive
可以简写成-i
如果使用了git rebase -i
那么git会打开一个UI界面,列出将要被复制到目标分支的备选提交记录,它还会显示每个提交记录的哈希值和提交说明,提交说明有助于你理解这个提交进行了哪些更改。它是复制一遍你的更改如何创建一条新的分支。
这个UI界面就是我们安装时候选择的默认编辑器,git会使用这个编辑器来打开一个文件,打开之后没有图形化操作,这任然需要我们使用命令去操作。git rebase -i HEAD~4
只操作当前记录向上的记录。这个界面打开之后我们可以做三件事情
pick
(每一条提交记录在开头都有状态,手动去修改它的状态可以决定它们是否存在或者删除) 的状态来完成,关闭就意味着你不想要这个提交记录)具体使用命令可以调出UI查看(具体使用命令都在编辑器打开的文件中有注释)
在一些分支上调试并解决bug之后我们不希望正一条分支都合并到主分支上,因为可能在bug分支中存在一些打印调试语句我们并不希望它们合并到主分支中,因此可以配合git cherry-pick 哈希值
命令来使用将分支中调试好的部分复制一份当新的提交记录来合并到主分支中。
使用git rebase -i [加上节点数量例如HEAD~2]
可以让节点重新排序,然后使用git commit -amend
对最前端的提交记录进行修改
命令git tag 标签名 某个记录的哈希值
可以指定某个记录的标签名是什么,可以对往后的相对引用提供便利。如果我们不指定某个记录的哈希值的话。Git会默认在后面加上当前head指向的记录
命令Git describe [这里写分支名或者某个提交记录的哈希值]
可以找出距离当前位置最近的标签,git describe
甚至后面可以不填,git默认为当前分支的当前位置开始找最近的标签
命令git checkout 分支名^2
可以选择第二个父提交,在一个合并提交的记录中想要灵活的选择某一个父提交的话需要使用^加上数字来指定返回那一条分支的父提交。
另外还支持链式操作git checkout HEAD~1^2~2
Git Fetch
命令可以将远程仓库中同步到本地仓库。git pull
命令可以把远程仓库的数据直接同步到工作区
命令git push
可以把本地仓库的数据推送到远程仓库。如果这条命令不带参数的话,会使用一个默认配置进行推送。默认配置在*push.default
*中,这个默认配置在git的不同版本中略有不同。
在使用git push
之后,数据推送到远程仓库中后,远程仓库的分支指向我们更新的最新。并且本地仓库中的代表远程仓库的分支也会指向最新的提交记录
在我们使用推送命令的时候,有可能我们本地仓库中的代表远程仓库中的分支和远程仓库中的分支不一致(也就是本地仓库和远程仓库中的数据、版本等不一致)。这些改变可能来着你的远程仓库协作者更新了远程仓库中的代码。而我们本地仓库所使用的还是旧版本的代码。这使得本地和远程数据不一致。在这个时候我们的push命令是会失败的。
最常见的解决办法就是:
git fetch
以上的这三步可以在push中使用参数来简写git pull --rebase
和git push
来实现
一般在我们克隆远程仓库的时候git就默认帮助我们设置的远程追踪,一般这个远程追踪分支在命名为master
当然我们也可以自定义追踪分支
git checkout -b totallyNotMaster o/master
就可以创建一个名为 totallyNotMaster
的分支,它跟踪远程分支 o/master
。
git branch -u o/master foo
这样 foo
就会跟踪 o/master
了。如果当前就在 foo 分支上, 还可以省略 foo:
git branch -u o/master
将非master分支的其他分支推送到远程仓库这是一个好办法,不用切换到master分支了
git push origin master
命令指定推送到远程仓库中的master分支(origin指远程仓库名称 master指远程仓库中需要推送的分支),那么git就会在本地仓库中查找和远程仓库分支master相关联的分支。找到之后会把本地分支在远程仓库分支中没有的提交推送到远程仓库。使用这条命令可以直接指定推送,而不必要切换到我们需要推送的分支。
同时我们还可以自定义推送的来源和目的地:git push origin foo:master
这样把本地foo分支的提交记录就推送到了远程仓库中的master分支。
如果我们要推送的远程仓库中没有我们指定的分支,那么git会帮助我们在远程仓库中创建一个新的分支,分支名就是我们指定的分支名
和git push的参数相类似,命令git fetch origin foo
会在远程仓库中找到foo分支并把它在本地仓库中没有的提交记录同步到本地仓库的fetch分支.
当然:同样适用git fetch foo^:bar
它会把远程仓库中的foo上一个提交记录同步到本地的bar。如果本地仓库中不存在bar分支,那么git同样会在本地仓库中创建一个bar分支
注意点:如果我们适用fetch和push的时候:前面的值留空会发生一些诡异的事情。
git push origin :bar
那么将会删除远程仓库中的bar分支本地仓库中的代表远程仓库bar分支的指向也会跟着删除
git fetch origin :bar
那么会在本地创建一个新的分支bar
git pull 实际上就是 fetch + merge 的缩写