什么是git?
git是目前世界上最先进的分布式版本控制系统(没有之一)
git特点
- 简单大气上档次
集中式VS分布式
先说集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,在把自己的活推送给中央服务器。中央服务器就好比一个图书馆,你要改一本书,必须先拿出来,然后改完了在还回去。
集中式版本控制系统最大的毛病就是必须联网才能功能,如果在局域网内还行,带宽够大,速度够快,可如果在互联网上遇到网速慢的话,可能提交一个10M的文件就需要好几分钟。
那分布式版本系统与集中式版本控制系统有何不同呢?首先,分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那么如何多人协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这是,你们之间,只需要把各自修改的地方推送给对方,就可以互相看到对方的修改了。
和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人的电脑里都有完整的版本库,某一个人的电脑坏了没关系,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是除了问题,那么所有人都没了。
在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们不在一个局域网内,两台电脑互相访问不了,因此分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,知识交换修改不方便而已。
当然,Git的优势绝不单单是不必联网这么简单,它还有极其强大的分支管理,把SVN远远抛在了后面
一、Git的安装
http://git-scm.com/
这里下载按照默认安装就好。。。
在桌面或者任意目录右键出现 Git Base Here 出现如下界面表示安装成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p92mSs9d-1631331109196)(C:\Users\chenx\AppData\Roaming\Typora\typora-user-images\image-20210911112811947.png)]
1.设置全局身份
因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址
$ git config --global user.name "Your Name"
$ git config --global user.email "You Email"
设置完成后在你的用户目录下会生成一个 .gitconfig 文件记录了这些信息
不单单只能配置name和email,你可以任意配置你想要的属性例如user.phone只是这两个是必须的
2.创建版本库
什么是版本库呢?版本库又叫仓库,你可以简单理解成一个目录,这个目录里面所有文件都可以呗Git管理起来,每个文件的修改,删除,Git都能跟踪,以便任何时候都可以追踪历史,或者在将来某个时刻可以“还原”
- 创建一个版本库非常简单,我们任意创建一个空的目录,进入目录右键 Git Base Here 进入命令界面
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹
#创建仓库
$ mkdir repository
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹
# 进入目录
$ cd repository/
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository
# 把目录编程一个版本库,执行仓库初始化命令
$ git init
# 查看目录 增加了一个.git文件
$ ls -a
./ ../ .git/
添加文件
这里明确一下,所有的版本控制系统,其实只能跟踪文本的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。版本控制系统可以告诉你每次的改动,比如在第5行加一个单词"code",在某一行删除了某个单词。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没办法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
不幸的是,Microsoft的Word格式是二进制格式,因此,版本控制系统是没法追踪Word文件的改动,如果要真正使用版本控制系统,就要以纯文本方式编写文件。
因为文本室友编码的,比如中文常用的GBK编码,日文有Shift_JIS编码,如果没有历史遗留问题,建议使用UTF-8编码,既没有冲突,又被所以平台支持。
现在我们编写一个readme.txt文件内容如下:
别拿自己当回事,要拿你做的事情当回事。
将该文件放到刚刚创建的版本目录中,子目录也行,然后我们将该文件放到Git仓库中
- 使用 git add 告诉Git,把文件添加到仓库:
$ git add readme.txt
执行如上命令,没有任何显示,这就对了,Unix的哲学就是“没有消息就是好消息”,说明添加成功
- 用命令 git commit告诉git,把文件提交到仓库
$ git commit -m '创建一个文件'
[master (root-commit) 6aec092] 创建一个文件 1 file changed, 1 insertion(+) create mode 100644 readme.txt
- 提交完毕后我们查看当前git版本状态
这里表示没有任何可提交的。
- 我们修改一下readme里的内容,再次查看
红色的部分代表新的文件
- 再次使用
Git add 文件名
把当前文件加入到暂存区 - 再次使用
git status
查看版本状态
红色部门代表暂存区有一个新的文件没有提交,提交之后才会进入版本库
- 使用
git commit -m '说明'
把暂存区提交到当前所在分支(master)
版本回退
- 相关命令
git log
查看当前分支的版本提交所有记录
git long --pretty=oneline
一行显示
git reset --hard HEAD^
向上回退一个版本 ^代表一个版本 ^^代表向上回头两个版本以此类推
我们可以看到HEAD指向了前一个版本
git reset --hard 6aec
回退到指定版本,这里版本号在少数的情况下可以缩写
工作区和暂存区
Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念
- 工作区(Working Directory)
就是你在电脑里能看到的目录,如我们的repository文件就是一个工作区: - 版本库(Repository)
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库
Git的版本库里存放了很多东西,其中最重要的就是成为stage(或者叫index)的暂存区,还有Git为我自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
前面我们所说的把文件往Git版本库里添加的时候,是分两部指向的:
- 第一步用
git add
把文件添加进去,实际上就是把文件修改添加到暂存区。- 第二步使用
git commit
提交更改,实际上就是把暂存区的所有文件内容提交到当前分支
因为我们创建Git版本库时,Git自动为我们创建了一个唯一一个master分支,所以,git commit
就是往master分支上提交更改,可以简单理解为,需要提交的文件通通放到暂存区,然后一次性提交暂存区的所有修改。
文件修改
- 现在工作区创建文件 ----
git add
到暂存区----git commit
到分支 - 相关命令
git diff head -- 文件名
查看当前文件和版本库区别
文件管理-撤销修改
- 情况1:数据只存在工作区
相关命令:git checkout -- readme.txt
丢弃工作区的修改,使用该命令可以撤销该文件的修改。
- 情况2:数据使用
git add
添加到暂存区
相关命令:git reset HEAD 文件名
移除暂存区该文件,在执行情况1的方式。
- 情况3:数据使用
git commit
到版本库- 使用版本回退
git reset --hard 版本号
- 使用版本回退
文件管理-删除文件
相关命令:
- 先删除
git rm -rf 文件名
如上图,我们指向了
git rm -rf 文件名
后查看git状态会发现有一个绿色的delete状态的文件,此命令类似于git add
因此我们也需要执行git commit -m '删除文件'
告诉分支将此文件删除,值得注意的是,删除并不是回退版本,而是会继续向上追加命令。
创建与分支合并
在版本回退里,你已经知道,每次提交,Git都把他们传承一条时间线,这条时间线就是一个分支。我们上面所说的,只有一条时间线,这个也叫做主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:
每次提交,master分支会都向前移动一步,这样,随着你不断提交,master分支的线也会越来越长。
当我们创建新的分支,例如dev分支,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
你看,Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,而工作区的文件都没任何变化,不过,从现在开始对工作去的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
加入我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法就是直接把master指向dev的当前提交,就完成了合并:
所以Git合并分支也很快!就改改指针,工作区内容也不变,合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后我们就剩下了一条master分支。
相关命令
- 创建dev分支,并切换到dev分支
git checkout -b dev
git branch dev
创建dev分支git checkou dev
切换分支git branch
查看分支git branch -d 分支名字
删除分支(删除分支的时候,需切换至其他分支才能删除)
场景: 我们切换至dev分支,然后使用
vim
进行文件修改,然后使用git status
状态查看我们肯定是可以看到有一条修改待提交暂存区的记录
然而我们在
git checkout master
后查看状态仍然发现有一条待提交的记录,这是为什么呢?
- 因为我们不管是在master分支还是dev分支上做的任何修改,这个修改都是在我们的工作区,也就是本地。而dev或者master都只是版本里的一个指针指向。
接下来我们在使用
git add
看看是否能解决这个问题。
我们在dev分支进行
git add readme.txt
后在切换至master分支查看状态,我们仍然会发现有一条待提交的文件显示,这是为什么呢?
- 因为我们使用
git add
命令后我们只是把文件提交到了版本库中的暂存区,而我们最终的指向是通过HEAD的指针的指向决定是dev还是master也就是说,暂存区的内容也是共享的。我在再在dev分支使用git commit
试试!
从dev分支提交后,我们可以发现解决了这个问题,并且在master分支上也无法看到dev分支修改的内容,有兴趣的可以自行试试。
git merge dev
合并分支
我们把dev分支刚刚修改的内容合并到master分支上,我们则需要在master分支上执行命令
我们在master分支上也可以看到刚刚dev上修改的内容了。
冲突解决
例如我们在dev分支上增加一行内容,然后master分支也进行了内容修改,然后我们在master分支上对dev进行合并就会出现冲突,那么这样情况就需要我们去手动解决冲突了。
# 切换至dev分支
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ git checkout dev
Switched to branch 'dev'
#在dev分支上对文件进行修改
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (dev)
$ vi readme.txt
# 提交至暂存区
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (dev)
$ git add readme.txt
# 提交文件至dev版本库
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (dev)
$ git commit -m '在dev上添加'
[dev 2740065] 在dev上添加
1 file changed, 1 insertion(+)
#切换至master分支
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (dev)
$ git checkout master
Switched to branch 'master'
#对文件进行修改
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ vim readme.txt
# 提交至暂存区
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ git add readme.txt
# 提交至master版本库
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ git commit -m '在master上提交'
[master fa78be2] 在master上提交
1 file changed, 1 insertion(+)
# 查看master分支上的内容,并无dev上修改的内容
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ cat readme.txt
第一行数据
在dev新增数据
在master上增加一行
#合并分支
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ git merge dev
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
# 我们发现出现了错误,并且出现了临时分支(master|MERGING)临时分支表示合并中,我们查看文件内容,出现了冲突内容。
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master|MERGING)
$ cat readme.txt
第一行数据
在dev新增数据
<<<<<<< HEAD
在master上增加一行
=======
dev添加一行数据
>>>>>>> dev
# vim进行手动冲突解决。
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master|MERGING)
$ vim readme.txt
# 提交
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master|MERGING)
$ git add .
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master|MERGING)
$ git status
On branch master
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: readme.txt
#合并完成
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master|MERGING)
$ git commit -m '合并提交'
[master 0cfd574] 合并提交
# 再次查看文件
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ cat readme.txt
第一行数据
在dev新增数据
在master上增加一行
dev添加一行数据
git log --graph
可以查看分支合并图
分支策略
通常,合并分支时候,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息,如果要强化之金庸Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息,我们可以来尝试一下 --no-ff 方式的git merge
git merge --no-ff -m 'merge with no-ff 提交' dev
合并分支时,加上–no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾静做过合并,而fast forward合并就看不出来曾经做过合并
分支管理-bug分支
软件开发种,bug就像家常便饭一样,有了bug就需要修复,在Git种,由于分支时如此的强大所以每个bug都可以通过一个临时分支来修复,修复后,合并分支,然后将临时分支删除。
场景: 当你接到一个bug 101的任务时,你会很自然的想到创建一个issue-101来修复它,但是此时当前正在dev上进行的工作还没有提交。如下:
前面我们介绍过,我们在dev上进行的修改在没有commit之前都是在工作区的,也就是在本地,因此我们即使切换到了master或者其他分支,此处都是会影响的,但是我此时我该功能预期还需要一天完成,而bug必须在两个小时内完成,怎么办?
git提供了 stash功能,可以把当前工作现场"储藏"起来,等以后修复香肠后继续工作
相关命令:
- git stash
储藏工作区
- git stash list
查看储藏的列表
- git stash pop
出栈
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ git checkout dev
Switched to branch 'dev'
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (dev)
$ vim readme.txt
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (dev)
$ git status
On branch dev
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (dev)
$ git stash
Saved working directory and index state WIP on dev: ea52634 在dev上提交
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (dev)
$ git checkout master
Switched to branch 'master'
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ git status
On branch master
nothing to commit, working tree clean
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ git checkout -b issue-101
Switched to a new branch 'issue-101'
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (issue-101)
$ vim readme.txt
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (issue-101)
$ git add readme.txt
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (issue-101)
$ git commit -m 'bug修复'
[issue-101 63c1d7a] bug修复
1 file changed, 1 insertion(+), 1 deletion(-)
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (issue-101)
$ git checkout master
Switched to branch 'master'
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ git merge issue-101
Updating 5f28df5..63c1d7a
Fast-forward
readme.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ git branch -d issue-101
Deleted branch issue-101 (was 63c1d7a).
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (master)
$ git checkout dev
Switched to branch 'dev'
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (dev)
$ git stash list
stash@{0}: WIP on dev: ea52634 在dev上提交
chenxh@DESKTOP-G1KAA8P MINGW64 ~/Desktop/新建文件夹/repository (dev)
$ git stash pop
On branch dev
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (3b2ef7b5fe4882357629e770848c73ac7d309808)
至此git的基本命令到此差不多都介绍完毕了,有不对的地方还请各位指点。
远程仓库使用gitee
-
创建SSH Key:
ssh-keygen
按照提示即可
然后会在用户目录下生成文件.ssh:
id_rsa :密钥
id_rsa.pub:公钥 -
登录gitee,配置ssh key
然后将id_rsa.pub里的内容复制进去即可。
-
添加远程仓库—新建仓库
-
生成后,会提供一个仓库地址
-
本地仓库,关联远程仓库
相关命令git remote add origin git@gitee.com:chenxh0428/test.git
没有消息就是好消息 -
把本地仓库内容推送到远程仓库上
相关命令:
git push origin master
发现远程gitee上有了本地的代码,至此推送至远程仓库结束 -
从远程仓库克隆
git clone git@gitee.com:chenxh0428/test.git
我们发现,我们从远程clone下来的代码发现没有dev分支,然后我们在远程仓库上是存在dev分支的,此时我们需要关联远程仓库。
git checkout -b dev origin/dev
常用命令整理
命令 | 说明 |
---|---|
git config --global user.name "Your Name" | 设置用户名 |
git config --global user.email "You Email" | 设置邮箱 |
git init | 初始化git,创建一个本地git版本库.git同时生成 |
git add 文件名 | 将本地文件从工作区提交至暂存区 . 代表提交全部 |
git commit -m '说明' | 将本地暂存区文件提交至本地版本库 |
git status | 查看当前版本库状态 |
git log | 查看当前分支的版本提交所有记录 |
git log --pretty=oneline | 查看版本提交记录 一行显示 |
git reset --hard HEAD^ | 向上回退一个版本 ^代表上个版本 ^^代表两个版本,以此类推 |
git reset --hard 版本号 | 回退到指定版本,在版本号不多的情况下可以进行缩写模糊匹配 |
git diff head --文件名 | 查看当前文件和版本库的区别 |
git checkout --文件名 | 丢弃工作区的修改,该命令可以撤销该文件的修改 |
git reset HEAD 文件名 | 移除暂存区的修改(使用git add后会提交至暂存区) |
git rm -rf 文件名 | 文件删除,此命令等于一个delete执行,需要我们进行commit提交 |
git checkout -b dev | 创建分支并切换分支 |
git branch dev | 创建分支 |
git checkout dev | 切换分支 |
git branch | 查看分支 |
git branch -d 分支名 | 删除分支 |
git merge dev | 合并分支 |
git merge --no-ff -m 'merge with no-ff 提交' dev | 禁用Fast forward模式合并 |
git stash | 储藏工作区 |
git stash list | 查看储藏列表 |
git stash pop | 出栈 |
ssh-keygen | 创建远程SSH key |
git remote add origin 仓库地址 | 本地仓库关联远程仓库 |
git push origin master | 将本地master分支所有内容推送到远程仓库 |
git pull origin master | 拉取远程仓库最新代码 |
git clone 仓库地址 | 从远程仓库克隆代码 |
git checkout -b dev origin/dev | 关联远程仓库。 |
git branch --set-upstream-to=origin/remote_branch your_branch | 本地分支关联远程分支origin/remote_branch:你本地对应的远程分支,your_branch:你本地分支 |
git push origin newbranch:newbranch | 新建一个远程分支 |
git push --set-upstream origin newbranch | 本地分支关联远程分支 |
git remote -v | 显示所有远程仓库 |
git remote show [remote] | 显示某个仓库信息 |
git remote add [shortname] [url] | 添加远程版本库 |
git remote rm name | # 删除远程仓库 |
git remote rename old_name new_name | 修改仓库名 |