常见版本控制器
集中式版本控制器
CSV/SVN
- 速度慢,必须联网
- 只有⼀个中央数据仓库,如果中央数据仓库挂了或者⽆法访问,所有的使用者无法使⽤SVN,无法法进行提交或备份操作
分布式版本控制器
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目
Git一开始是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件
Git优点:
- 无中央服务器,每个人的电脑都是一个完整的版本库
- 完全性能更高
- 通常有一台充当“中央服务器”的电脑,仅仅作为方便“交换”大家的修改
Git和SVN的区别:
- Git 是分布式的,SVN 不是
- Git 把内容按元数据方式存储,而 SVN 是按文件
- Git 分支和 SVN 的分支不同
- Git 没有一个全局的版本号,而 SVN 有
- Git 的内容完整性要优于 SVN:Git 的内容存储使用的是 SHA-1 哈希算法
Git安装
Git官网下载https://git-scm.com/downloads
- yum安装git
[root@server1 ~]# yum install git -y
- 配置本地用户信息
[root@server1 ~]# git config --global user.name "sy"
[root@server1 ~]# git config --global user.email "sy@qq.com"
[root@server1 ~]# git config --global color.ui true
[root@server1 ~]# git config --list
user.name=sy
user.email=sy@qq.com
color.ui=true
- 创建并初始化版本库
[root@server1 ~]# mkdir my_git
[root@server1 ~]# cd my_git/
[root@server1 my_git]# git init
初始化空的 Git 版本库于 /root/my_git/.git/
[root@server1 my_git]# ls -a
. .. .git
[root@server1 my_git]# ls .git/
branches config description HEAD hooks info objects refs
Git介绍
Git的组织结构如下图所示:
工作目录
- 当前所在的目录就是工作目录
暂存区域
.git
不算⼯作区,只是git的版本库- 版本库中只有暂存区和自动创建的master分⽀及指向master的⼀个指针HEAD
- git跟踪的是每次修改而不是文件,如果不将修改添加到暂存区是无法进行提交的
.git
文件夹中的文件介绍branches # 分支目录
config # 定义项目特有的配置选项
description # 仅供git web程序使用
HEAD # 指示当前的分支
hooks # 包含git钩子文件
info # 包含一个全局排除文件
objects # 本地仓库,存放所有的数据内容,有info和pack两个文件夹
refs # 存放指向数据(分支)的提交对象的指针
index # 保存暂存信息,在执行git init的时候,这个文件还没有
- 远程仓库:Github、Gitee等
常规使用
日常使用的命令如下图所示:
- 添加文件到仓库中,语法:
git add 文件名
[root@server1 my_git]# echo "hello world" > README.txt
[root@server1 my_git]# git add README.txt
- 查看Git状态,语法:
git status
[root@server1 my_git]# git status
# 位于分支 master
#
# 初始提交
#
# 要提交的变更:
# (使用 "git rm --cached <file>..." 撤出暂存区)
#
# 新文件: README.txt
#
- 提交文件到仓库,语法:
git commit -m "注释内容"
[root@server1 my_git]# git commit -m "write a README.txt"
[master(根提交) 0943734] write a README.txt
1 file changed, 1 insertion(+)
create mode 100644 README.txt
[root@server1 my_git]# git status
# 位于分支 master
无文件要提交,干净的工作区
- 修改文件,再次提交到仓库,语法:
git commit -a -m "注释内容"
[root@server1 my_git]# echo "hello linux" > README.txt
[root@server1 my_git]# git status
# 位于分支 master
# 尚未暂存以备提交的变更:
# (使用 "git add <file>..." 更新要提交的内容)
# (使用 "git checkout -- <file>..." 丢弃工作区的改动)
#
# 修改: README.txt
#
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
[root@server1 my_git]# git commit -a -m "modify a README.txt"
[master 0ef4b46] modify a README.txt
1 file changed, 1 insertion(+), 1 deletion(-)
[root@server1 my_git]# git status
# 位于分支 master
无文件要提交,干净的工作区
- git commit 命令的-a选项可将所有被修改或者已删除的且已经被git管理的文档提交到仓库中
- 不能提交新文件,对于新文件还是需要先使用git add再使用git commit
- 查看文件内容改动情况,语法:
git diff 文件名
[root@server1 my_git]# echo "hello python" > README.txt
[root@server1 my_git]# git diff README.txt
diff --git a/README.txt b/README.txt
index ce09bf3..0ea61c1 100644
--- a/README.txt
+++ b/README.txt
@@ -1 +1 @@
-hello linux
+hello python
PS:只能查看当前未到仓库中的文件与已经到仓库中的同名文件进行对比
-
号代表与上一个文件相比少的内容
+
号代表与上一个文件相比多的内容
查看历史记录
git log
:详细展示git log --oneline
:精简展示git reflog
:能获取历史版本号
[root@server1 my_git]# git log
commit 0ef4b466581f3675b708db7e2d0d25b232c4c143
Author: sy <sy@qq.com>
Date: Mon Mar 7 01:20:08 2022 +0800
modify a README.txt
commit 09437342b5e6f31ebe6450906a7f6f057975585b
Author: sy <sy@qq.com>
Date: Mon Mar 7 01:16:39 2022 +0800
write a README.txt
[root@server1 my_git]# git log --oneline
0ef4b46 modify a README.txt
0943734 write a README.txt
[root@server1 my_git]# git reflog
0ef4b46 HEAD@{0}: commit: modify a README.txt
0943734 HEAD@{1}: commit (initial): write a README.txt
- 删除文件,语法:
git rm 文件名
(不能删除在暂存区中的文件)
[root@server1 my_git]# git rm README.txt
rm 'README.txt'
[root@server1 my_git]# git commit -m "delete a README.txt"
[master 02cdd1a] delete a README.txt
1 file changed, 1 deletion(-)
delete mode 100644 README.txt
[root@server1 my_git]# git status
# 位于分支 master
无文件要提交,干净的工作区
分支
分支介绍
分支就是平行空间,假设你在某个手机系统研发拍照功能,代码已经完成了80%,但如果将这不完整的代码直接提交到git仓库中,又有可能影响到其他人的工作,此时我们便可以在该软件的项目之上创建一个名叫拍照的分支,这种分支只会属于你自己,而其他人看不到,等代码编写完成后再与原来的项目主分支合并即可,这样既能保证代码不丢失,又不影响其他人工作
一般在实际的项目开发中,尽量保持master分支是非常稳定的,仅用于发布新版本,平时不要随便直接修改里面的数据文件,而工作的时候则可以新建不同的工作分支,等到工作完成后再合并到master分支上面,所以团队的合作分支看起来会像很多树枝一样
命令集合
查询分支
# 列出所有本地分⽀
$ git branch
# 列出所有远程分⽀
$ git branch -r
# 列出所有本地分⽀和远程分⽀
$ git branch -a
新建分支
# 新建⼀个分⽀,但依然停留在当前分⽀
$ git branch [branch-name]
# 新建⼀个分⽀,并切换到该分⽀
$ git checkout -b [branch]
# 新建⼀个分⽀,指向指定commit
$ git branch [branch] [commit]
# 新建⼀个分⽀,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]
切换分支
# 切换到指定分⽀,并更新⼯作区
$ git checkout [branch-name]
# 切换到上⼀个分⽀
$ git checkout -
合并分支
# 合并指定分⽀到当前分⽀
$ git merge [branch]
# 选择⼀个commit,合并进当前分⽀
$ git cherry-pick [commit]
示例:
[root@server1 my_git]# git branch
master
* photo
[root@server1 my_git]# echo "hello world" > test.txt
[root@server1 my_git]# git add test.txt
[root@server1 my_git]# git commit -m "add a test.txt"
[root@server1 my_git]# ls
test.txt
[root@server1 my_git]# git checkout master
切换到分支 'master'
[root@server1 my_git]# echo "hello linux" > TEST.txt
[root@server1 my_git]# git add TEST.txt
[root@server1 my_git]# git commit -m "add a TEST.txt"
[root@server1 my_git]# ls
TEST.txt
# 将photo合并到当前分支即master分支
[root@server1 my_git]# git merge photo
Merge made by the 'recursive' strategy.
test.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 test.txt
[root@server1 my_git]# ls
test.txt TEST.txt
追踪分支
# 建⽴追踪关系,在现有分⽀与指定的远程分⽀之间
$ git branch --set-upstream [branch] [remote-branch]
删除分支
# 删除分⽀
$ git branch -d [branch-name]
# 删除远程分⽀
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]
筛选分支
# 检出版本v2.0
$ git checkout v2.0
# 从远程分⽀develop创建新本地分⽀devel并检出
$ git checkout -b devel origin/develop
# 检出head版本的README⽂件(可⽤于修改错误回退)
$ git checkout -- README
标签
- 给状态新建标签
# 给当前状态打标签
$ git tag -a v1.0 -m " version 1.0"
# 指定某次状态打标签
$ git tag -a v2.0 [哈希值] -m "version 2.0"
- 给commit新建标签
# 新建⼀个tag在当前commit
$ git tag [tag]
# 新建⼀个tag在指定commit
$ git tag [tag] [commit]
- 查看标签信息
# 查看所有标签信息
$ git tag
# 查看指定标签信息
$ git show v1.0
- 以标签回滚
git reset --hard v2.0
- 删除标签
# 删除本地标签
$ git tag -d v1.0
# 删除远程标签
$ git push origin :refs/tags/[tagName]
- 提交标签
# 提交指定tag
$ git push [remote] [tag]
# 提交所有tag
$ git push [remote] --tags
- 新建分支指定标签
$ git checkout -b [branch] [tag]
远程同步
# 下载远程仓库的所有变动
$ git fetch [remote]
# 显示所有远程仓库
$ git remote -v
# 显示某个远程仓库的信息
$ git remote show [remote]
# 增加⼀个新的远程仓库,并命名
$ git remote add [shortname] [url]
# 取回远程仓库的变化,并与本地分⽀合并
$ git pull [remote] [branch]
# 推送本地指定分⽀到远程仓库
$ git push [remote] [branch]
# 推送所有分⽀到远程仓库
$ git push [remote] --all
# 强⾏推送当前分⽀到远程仓库,即使有冲突
$ git push [remote] --force
直接下载整个仓库
[root@server1 ~]# git clone https://gitee.com/Yimoqingfeng/git_test
正克隆到 'git_test'...
Username for 'https://gitee.com': Yimoqingfeng
Password for 'https://Yimoqingfeng@gitee.com':
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 10 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (10/10), done.
[root@server1 ~]# ls git_test/ -a
. .. .git .gitignore LICENSE
撤销回滚
# 恢复暂存区的指定⽂件到⼯作区
$ git checkout [file]
# 恢复某个commit的指定⽂件到暂存区和⼯作区
$ git checkout [commit] [file]
# 恢复暂存区的所有⽂件到⼯作区
$ git checkout .
# 重置暂存区的指定⽂件,与上⼀次commit保持⼀致,但⼯作区不变
$ git reset [file]
# 重置暂存区与⼯作区,与上⼀次commit保持⼀致
$ git reset --hard
# 重置当前分⽀的指针为指定commit,同时重置暂存区,但⼯作区不变
$ git reset [commit]
# 重置当前分⽀的HEAD为指定commit,同时重置暂存区和⼯作区,与指定commit⼀致
$ git reset --hard [commit]
# 重置当前HEAD为指定commit,但保持暂存区和⼯作区不变
$ git reset --keep [commit]
# 新建⼀个commit,⽤来撤销指定commit
# 后者的所有变化都将被前者抵消,并且应⽤到当前分⽀
$ git revert [commit]
# 暂时将未提交的变化移除,稍后再移⼊
$ git stash
$ git stash pop
Gitee仓库
Github仓库使用和Gitee仓库使用是相似的,由于Github对网络要求较高,因此这里使用Gitee进行实验
- 本地仓库
[root@server1 ~]# mkdir test_git
[root@server1 ~]# cd test_git/
# 初始化本地仓库
[root@server1 test_git]# git init
初始化空的 Git 版本库于 /root/test_git/.git/
# 创建文件
[root@server1 test_git]# echo "hello" > README.md
# 存入暂存区域
[root@server1 test_git]# git add README.md
# 提交文件到本地仓库
[root@server1 test_git]# git commit -m "add a README.md"
[root@server1 test_git]# ls
README.md
# 再创建一个新的分支photo
[root@server1 test_git]# git branch photo
[root@server1 test_git]# git checkout photo
# 创建文件
[root@server1 test_git]# echo "my photo" > photo.txt
# 存入暂存区域
[root@server1 test_git]# git add photo.txt
# 提交文件到本地仓库
[root@server1 test_git]# git commit -m "add a photo.txt"
[root@server1 test_git]# ls
photo.txt README.md
# master分支中的内容,在其他分支中也会存在
- 在Gitee中创建一个新的仓库
- 将本地的仓库分支推送到远程的Gitee仓库
[root@server1 test_git]# git push https://gitee.com/Yimoqingfeng/git_test photo
Username for 'https://gitee.com': Yimoqingfeng
Password for 'https://Yimoqingfeng@gitee.com':
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), 457 bytes | 0 bytes/s, done.
Total 6 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.3]
remote: Create a pull request for 'photo' on Gitee by visiting:
remote: https://gitee.com/Yimoqingfeng/git_test/pull/new/Yimoqingfeng:photo...Yimoqingfeng:master
To https://gitee.com/Yimoqingfeng/git_test
* [new branch] photo -> photo
可以看到photo分支被推送到了远程仓库,分支数变为2
- 将Gitee仓库中的内容拉取到本地仓库的master分支
[root@server1 test_git]# git pull https://gitee.com/Yimoqingfeng/git_test/ master
Username for 'https://gitee.com': Yimoqingfeng
Password for 'https://Yimoqingfeng@gitee.com':
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), done.
来自 https://gitee.com/Yimoqingfeng/git_test
* branch master -> FETCH_HEAD
Merge made by the 'recursive' strategy.
.gitignore | 13 ++
LICENSE | 661 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 674 insertions(+)
create mode 100644 .gitignore
create mode 100644 LICENSE
可以发现master仓库中也有了远程仓库的内容
[root@server1 test_git]# git branch
* master
photo
[root@server1 test_git]# ls -a
. .. .git .gitignore LICENSE README.md