Git的基本使用
Git
本文是本人学习廖雪峰的Git教程后的总结
1. Git是分布式版本控制系统
版本控制系统分为分布式和集中式两种
1.1 什么是集中式版本控制系统
集中式版本控制系统,版本库是集中存放在*服务器的,而工作的时候,都是使用自己的电脑,所以要先从*服务器取得最新的版本,然后开始工作,工作完了,再把自己的成果推送给*服务器。
集中式版本控制系统最大的毛病就是必须联网,必须联网才能工作!
仅仅只是局域网还好,带宽够大,速度够快。但在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟。
1.2 Git作为分布式版本控制系统
分布式版本控制系统根本没有“*服务器”,每个人的电脑上都有一个完整的版本库。这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。多人协作时,需把各自的修改推送给别人,就可以看到推送者的修改了。
和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的*服务器要是出了问题,所有人都没法干活了。
但是实际应用中,很少在同一局域网工作,因此分布式版本控制系统通常也有一台充当“*服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
2. 仓库结构
2.1 工作区
工作区就是我们电脑本地能看到的文件
.git是隐藏文件夹,里面是记录版本库的信息,不要去修改它,以免版本库损坏
2.2 版本库
(图片来源网络,侵删)
HEAD是一个指向master分支(它也是一个指针,这个指针的指向是当前版本)的一个指针)
3. Git管理的是修改,而不是文件本身
3.1 创建一个Git本地仓库
会用到的一些语法
$ cd <path>
// 跳转到<path>路径下
$ mkdir <name>
// 当前目录下创建一个名为<name>的文件夹
$ git init
// 将当前目录初始化为本地仓库
例如:
我的电脑 MINGW64 /g/warehouse
$ mkdir test
我的电脑 MINGW64 /g/warehouse
$ cd test
我的电脑 MINGW64 /g/warehouse/test
$ git init
Initialized empty Git repository in G:/warehouse/test/.git/
首先创建一个test文件夹,然后跳转到此目录下,将其初始化为本地仓库
3.2 管理修改
会用到的一些语法
$ touch <filename.***>
// 创建文件<filename.***>
$ vi <filename.***>
// 使用vi编辑器编辑文件,具体操作自行查阅
$ git add <filename.***>
// 添加文件到暂存区
$ git status
// 查看暂存区状态
$ git commit -m "<commit message>"
// 提交暂存区到分支,每次提交写上"<commit message>"是个好习惯
例如:
我的电脑 MINGW64 /g/warehouse/test (master)
$ touch README.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ vi README.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ git add README.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ git commit -m "add README.md"
[master (root-commit) 48711df] add README.md
1 file changed, 1 insertion(+)
create mode 100644 README.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
nothing to commit, working tree clean
3.3 撤销修改
会用到的一些语法
$ git checkout -- <filename.***>
// 撤销<filename.***>的修改
$ git reset HEAD <filename.***>
// 已经add时,将<filename.***>返回到版本库状态,再使用git checkout -- <filename.md>
例如:
3.3.1 未add到暂存区时
我的电脑 MINGW64 /g/warehouse/test (master)
$ git checkout -- README.md
还未add时,只需使用git checkout -- <filename.***>
撤销<filename.***>的修改
3.3.2 已经add到暂存区
我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
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.md
no changes added to commit (use "git add" and/or "git commit -a")
我的电脑 MINGW64 /g/warehouse/test (master)
$ git add README.md
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory
我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ git reset HEAD README.md
Unstaged changes after reset:
M README.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
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.md
no changes added to commit (use "git add" and/or "git commit -a")
我的电脑 MINGW64 /g/warehouse/test (master)
$ git checkout -- README.md
已经add时,先使用git reset HEAD <filename.***>
将<filename.***>返回到版本库状态,再使用git checkout -- <filename.md>
3.4 删除文件
会用到的一些语法
$ git rm <filename.***>
// 移除文件<filename.***>
例如:
// 新建一个文件test.md,并提交到版本库
我的电脑 MINGW64 /g/warehouse/test (master)
$ touch test.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
test.md
nothing added to commit but untracked files present (use "git add" to track)
我的电脑 MINGW64 /g/warehouse/test (master)
$ git add test.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ git commit -m "add test.md"
[master a633db8] add test.md
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test.md
// 下面是删除此文件
我的电脑 MINGW64 /g/warehouse/test (master)
$ git rm test.md
rm 'test.md'
我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: test.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ git commit -m "delete test.md"
[master 9c1123e] delete test.md
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 test.md
我的电脑 MINGW64 /g/warehouse/test (master)
$ git status
On branch master
nothing to commit, working tree clean
移除之后需要git commit
提交到版本库,若是误删且还未提交到版本库,即可使用git checkout -- <filename.***>
恢复
4. 远程仓库
4.1 关联远程仓库
$ git remote add origin aaa@qq.com:<your username>/learngit.git
4.2 推送到远程仓库
$ git push -u origin master
由于远程库是空的,我们第一次推送master
分支时,加上了-u
参数,Git不但会把本地的master
分支内容推送的远程新的master
分支,还会把本地的master
分支和远程的master
分支关联起来,在以后的推送或者拉取时就可以简化命令。
后面的推送:
$ git push origin <name>
// 推送到<name>分支
4.3 从远程仓库克隆
$ git clone aaa@qq.com:<your username>/gitskills.git
注意:这里克隆下来的只有master
分支,若要在其他分支上开发,必须创建远程origin
的<name>
分支到本地
$ git checkout -b <name> origin/<name>
5. 分支管理
5.1 创建与合并分支
会用到的语句:
$ git branch
// 打印所有分支,*代表当前分支
$ git branch -d <name>
// 删除<name>分支,前提时已经合并的分支
$ git branch -D <name>
// 强行删除<name>分支,同于未被合并的分支
$ git switch <name>
// 切换到已有的分支<name>
创建时使用语句:
$ git branch <name>
$ git checkout <name>
// 创建名为<name>的分支,并切换到<name>分支
$ git checkout -b <name>
// 此句与上两句等效
$ git switch -c <name>
// 但是Git更鼓励使用此语句
合并时使用的语句:
$ git merge <name>
// 快速合并(Fast-forward),将当前分支合并到<name>分支,但是一旦删除<name>分支,就会失去分支信息
$ git merge --no-ff -m "merge with no-ff" <name>
// 禁用Fast-forward的合并,同时会commit,即便分支删除,也会保留分支信息
查看合并历史
$ git log --graph --pretty=oneline --abbrev-commit
5.2 快照
会用到的语句:
$ git stash
// 将当前的工作现场储存起来
$ git stash apply
// 恢复工作现场
$ git stash drop
// 删除之前储存的工作现场
$ git stash pop
// 恢复工作现场的同时删除之前储存的工作现场
5.3 解决冲突
为什么会冲突呢?很简单,两个分支从一个起点出发,向着两个不同的方向并行,要合并时两个分支的内容不一样,比如同一个文件的内容时不一样的,此时Git会告诉你合并冲突了,要你手动修改以解决冲突。
Git用
<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容,我们进行选择性的修改就行
5.4 分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本;
你和你的小伙伴们每个人都在dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature
分支,在上面开发,完成后,合并,最后,删除该feature
分支。
所以,团队合作的分支看起来就像这样:(引用廖雪峰的图)
哪些分支需要推送,哪些不需要呢?
-
master
分支是主分支,因此要时刻与远程同步; -
dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步; -
bug
分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug; -
feature
分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
5.5 Rebase(变基)
还没有领略其中的奥义,大佬们可以看看廖雪峰大神的.
6. 标签管理
会用到的语句:
$ git tag <name>
// 创建新标签,默认打在最新的一次commit上
$ git tag
// 查看所有标签,注意,标签不是按时间顺序列出,而是按字母排序的。
$ git tag <name> <commit id>
// 给<commit id>打上标签<name>
$ git show <name>
// 显示标签的信息
$ git tag -d <name>
// 删除标签,因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除
$ git push origin <name>
// 推送某个标签到远程
$ git push origin --tags
// 推送所有未推送的标签到远程
$ git push origin :refs/tags/<name>
// 删除一个远程标签,先从本地删除
7. 命令行小结
7.1 文件管理
显示当前路径
$ pwd
新建文件
$ touch <filename.***>
编辑文件(使用vi编辑器,关于vi的命令行自行查阅)
$ vi <filename.***>
新建文件夹
$ mkdir <name>
将当前目录初始化为本地仓库
$ git init
跳转
返回上一级的
<path>
是..
$ cd <path>
添加文件到暂存区
$ git add <filename.***>
从暂存区移除文件
$ git rm --cache <filename.***>
查看暂存区状态
$ git status
提交暂存区到版本库
$ git commit -m "<commit message>"
7.2 打印日志(git log 类)
$ git log
// 打印日志,内容繁多
$ git log --pretty=oneline
// 打印简单的日志
$ git reflog
// 打印所有的日志,包括被删除的
$ git log --graph --pretty=oneline --abbrev-commit
// 打印分支信息
7.3 远程仓库
关联远程的新仓库
$ git remote add origin aaa@qq.com:<your username>/<name>.git
第一次推送到远程仓库
$ git push -u origin master
后期的推送
$ git push origin <name>
将远程仓库克隆到本地(默认master
分支)
git clone aaa@qq.com:<your username>/<name>.git
注意:这里克隆下来的只有master
分支,若要在其他分支上开发,必须创建远程origin
的<name>
分支到本地
$ git checkout -b <name> origin/<name>
拉取最新的提交
$ git pull
可能会失败,因为没有建立分支于远程分支的链接,命令如下
$ git branch --set-upstream-to=origin/<name> <name>
7.4 分支
打印所有分支,*代表当前分支
$ git branch
创建时使用语句:
$ git branch <name>
$ git checkout <name>
// 创建名为<name>的分支,并切换到<name>分支
$ git checkout -b <name>
// 此句与上两句等效
$ git switch -c <name>
// 但是Git更鼓励使用此语句
合并时使用的语句:
$ git merge <name>
// 快速合并(Fast-forward),将当前分支合并到<name>分支,但是一旦删除<name>分支,就会失去分支信息
$ git merge --no-ff -m "merge with no-ff" <name>
// 禁用Fast-forward的合并,同时会commit,即便分支删除,也会保留分支信息
删除<name>
分支,前提时已经合并的分支
$ git branch -d <name>
强行删除<name>
分支,同于未被合并的分支
$ git branch -D <name>
切换到已有的分支<name>
$ git switch <name>
临时储存还未提交的分支
$ git stash
// 将当前的工作现场储存起来
$ git stash apply
// 恢复工作现场
$ git stash drop
// 删除之前储存的工作现场
$ git stash pop
// 恢复工作现场的同时删除之前储存的工作现场
7.5 标签
创建新标签,默认打在最新的一次commit上
$ git tag <name>
查看所有标签,注意,标签不是按时间顺序列出,而是按字母排序的
$ git tag
给打上标签
$ git tag <name> <commit id>
显示标签的信息
$ git show <name>
删除标签,因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除
$ git tag -d <name>
推送某个标签到远程
$ git push origin <name>
推送所有未推送的标签到远程
$ git push origin --tags
删除一个远程标签,先从本地删除
$ git push origin :refs/tags/<name>