git基础
创建版本库
- -mkdir 名称:创建一个目录
- -cd 名称 :进入名称对应文件夹
- -pwd :查看当前目录结构
- -git init:将目录变成管理仓库,细心的读者可以发现当前目录下多了一个
.git
的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。 - -ls -ah :列表目录,可以查看影藏目录
把文件添加到版本库
- -git add 文件名:告诉Git,把文件添加到仓库
- 可以提交多个文件如:
git add "xxx" "xxx"
- 可以提交多个文件如:
- -git commit:提交文件
- -m:可以再后面续写本次提交的说明如
-m "xxx"
- -m:可以再后面续写本次提交的说明如
时光穿梭机
查看修改的文件
-git status :查看结果,具体修改了什么文件
-git diff 文件名:查看文件名指定的文件做了哪些修改“详细”
$ git diff readme.txt diff --git a/readme.txt b/readme.txt index 46d49bf..9247db6 100644 --- a/readme.txt +++ b/readme.txt @@ -1,2 +1,2 @@ -Git is a version control system. +Git is a distributed version control system. Git is free software. //可看出添加了distribute这个单词
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#### 版本回退
+ -git log:查看日志历史记录了
+ ```java
$ git log
commit 1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master)
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:06:15 2018 +0800
append GPL
commit e475afc93c209a690c39c13a46716e8fa000c366
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:03:36 2018 +0800
add distributed
commit eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 20:59:18 2018 +0800
wrote a readme file–pretty=oneline
$ git log --pretty=oneline 1094adb7b9b3807259d8cb349e7df1d4d6477073 (HEAD -> master) append GPL e475afc93c209a690c39c13a46716e8fa000c366 add distributed eaadf4e385e865d25c48e7ca9c8395c3f7dfaef0 wrote a readme file //前半部分问版本号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
+ -git reset :版本回退
+ -- hard HEAD^:退回到上一个版本
+ -- hard HEAD^^:退回到上上一个版本
+ -- hard HEAD~100:退回到上100个版本
+ -- hard 1094a...:退回到指定id的版本,不用写权,git会自动匹配
+ -git reflog :用来记录每一次命令
##### 小结
+ Git的版本回退速度非常快,因为Git在内部有个指向当前版本的`HEAD`指针,当你回退版本的时候,Git仅仅是把HEAD从指向`append GPL改为指向`add distributed`然后顺便把工作区的文件更新了。所以你让`HEAD`指向哪个版本号,你就把当前版本定位在哪

+ `HEAD`指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令`git reset --hard commit_id`。
+ 穿梭前,用`git log`可以查看提交历史,以便确定要回退到哪个版本。
+ 要重返未来,用`git reflog`查看命令历史,以便确定要回到未来的哪个版本。
#### 工作区和暂存区
##### 工作区
+ 就是你在电脑里能看到的目录,比如我的`learngit`文件夹就是一个工作区:

##### 版本库(Repository)
+ 工作区有一个隐藏目录`.git`,这个不算工作区,而是Git的版本库。
+ Git的版本库里存了很多东西,其中最重要的就是称为**stage**(或者叫index)的暂存区,还有Git为我们自动创建的第一个**分支**`master`,以及指向`master`的一个**指针**叫`HEAD`。

+ 分支和`HEAD`的概念我们以后再讲。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用`git add`把文件添加进去,实际上就是**把文件修改添加到暂存区**;
第二步是用`git commit`提交更改,实际上就是**把暂存区的所有内容提交到当前分支**。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个`master`分支,所以,现在,`git commit`就是往`master`分支上提交更改。
你可以简单理解为,**需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改**。
#### 管理修改
+ git管理的只是修改,而不是文件
+ 你又理解了Git是如何跟踪修改的,每次修改,如果不用`git add`到暂存区,那就不会加入到`commit`中。
#### 撤销修改
+ -git checkout -- test.txt :把test.txt`文件在工作区的修改全部撤销,这里有两种情况:
+ 自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态
+ 已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态
+ **注意**:`git checkout -- file`命令中的`--`很重要,没有`--`,就变成了“切换到另一个分支”的命令
+ -git reset HEAD test.txt:可以把暂存区的修改撤销掉(unstage),重新放回工作区
+ 可以再接git checkout -- test.txt将工作区的文件改回原先的状态
+ 小结:
+ 当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令`git checkout -- file`。
+ 当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令`git reset HEAD <file>`,就回到了场景1,第二步按场景1操作。
+ 已经提交了不合适的修改到版本库时,想要撤销本次提交,参考[版本回退](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013744142037508cf42e51debf49668810645e02887691000)一节,不过前提是没有推送到远程库
#### 删除文件
+ -rm test.txt:将工作区中指定的文件删除
+ -git rm test.txt:git会检测到之前删除的文件,这个命令会从版本库删除文件名指定文件
+ 如果删错了
+ -git checkout -- test.txt:其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
### 远程仓库
+ $ ssh-keygen -t rsa -C "youremail@example.com"
+ 你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。
如果一切顺利的话,可以在用户主目录里找到`.ssh`目录,里面有`id_rsa`和`id_rsa.pub`两个文件,这两个就是SSH Key的秘钥对,`id_rsa`是私钥,不能泄露出去,`id_rsa.pub`是公钥,可以放心地告诉任何人。
+ 登陆GitHub,打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴`id_rsa.pub`文件的内容:

+ 点“Add Key”,你就应该看到已经添加的Key:

+ 为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
### 从远程库克隆
+ $ git clone https://github.com/646190632/Jiao:克隆远程仓库的项目到本地,git支持多种协议
### 分支管理
#### 时间线
+ 每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即`master`分支。
+ `HEAD`严格来说不是指向提交,而是指向`master`,`master`才是指向提交的,所以,`HEAD`指向的就是当前分支。

#### 创建分支
+ 当我们创建新的分支,例如`dev`时,Git新建了一个指针叫`dev`,指向`master`相同的提交,再把`HEAD`指向`dev`,就表示当前分支在`dev`上
+ Git创建一个分支很快,因为除了增加一个`dev`指针,改改`HEAD`的指向,工作区的文件都没有任何变化

+ 对工作区的修改和提交就是针对`dev`分支了,比如新提交一次后,`dev`指针往前移动一步,而`master`指针不变

+ 代码实现
```java
$ git checkout -b dev
Switched to a new branch 'dev'
//git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
查看当前分支
- 代码实现
- 用
git branch
命令查看当前分支:
1 |
|
合并分支
- 假如我们在
dev
上的工作完成了,就可以把dev
合并到master
上。Git怎么合并呢?最简单的方法,就是直接把master
指向dev
的当前提交,就完成了合并:
- 代码实现
1 |
|
- 注意:上面的
Fast-forward
信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master
指向dev
的当前提交,所以合并速度非常快。- 当然,也不是每次合并都能
Fast-forward
,我们后面会讲其他方式的合并。
- 当然,也不是每次合并都能
分支的删除
- 可以删除
dev
分支。删除dev
分支就是把dev
指针给删掉,删掉后,我们就剩下了一条master
分支:
- 代码实现
1 |
|
- 因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在
master
分支上工作效果是一样的,但过程更安全。
解决冲突
- git冲突提示不仅会在命令行中,还在文件中会显示
1 |
|
- 如果出现冲突,根据实际情况修改原有冲突文件,两个分支分再次别提交到仓库,再次合并
$ git log --graph --pretty=oneline --abbrev-commit
:可以通过日志查看解决冲突进程
分支管理策略
Fast forward
模式:这种模式下,删除分支后,会丢掉分支信息。 因为fast forward
合并就看不出来曾经做过合并。--no-ff
参数用于禁用该模式
- 如果禁用Fast forward模式的话,**Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息 **
- 在实际开发中,我们应该按照几个基本原则进行分支管理:
- 首先,
master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活; - 那在哪干活呢?干活都在
dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本; - 你和你的小伙伴们每个人都在
dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。 - 所以,团队合作的分支看起来就像这样:
- 首先,
Bug分支
- 软件开发中,bug就像家常便饭一样。有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
$ git stash
功能 :可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作- 关于恢复储藏起来的工作
- 用
git stash apply
恢复,但是恢复后,stash内容并不删除,你需要用git stash drop
来删除; - 用
git stash pop
,恢复的同时把stash内容也删了:
- 用
- 注意:
- 可以多次使用stash功能
$ git stash apply stash@{0}
可以选择取出指定的stash内容
Feature分支
多人协作
- 当你从远程仓库克隆时,实际上Git自动把本地的
master
分支和远程的master
分支对应起来了,并且,远程仓库的默认名称是origin
。 $ git remote
:查看远程库的信息- 参数
-v
查看详细信息
- 参数
推送分支
$ git push 远程库 要推送的分支
:把该分支上的所有本地提交推送到远程库 。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:- 关于哪些分支需要推送
master
分支是主分支,因此要时刻与远程同步;dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;- bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
- feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发
抓取分支
$ git branch --set-upstream-to=origin/dev dev
:首先需要将本地的分支和远程的分支链接,此处设置dev
和origin/dev
的链接$ git pull
:用git pull
把最新的提交从origin/dev
抓下来
小结
- 多人协作的工作模式通常是这样:
- 首先,可以试图用
git push origin <branch-name>
推送自己的修改; - 如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并; - 如果合并有冲突,则解决冲突,并在本地提交;
- 没有冲突或者解决掉冲突后,再用
git push origin <branch-name>
推送就能成功!
- 首先,可以试图用
rebase
1 |
|
$ git rebase
:Git把我们本地的提交“挪动”了位置,放到了f005ed4 (origin/master) set exit=1
之后,这样,整个提交历史就成了一条直线- rebase操作可以把本地未push的分叉提交历史整理成直线;
- rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比
标签管理
- 标签都只存储在本地,不会自动推送到远程
创建标签
$ git tag 版本
:打一个新标签- 可用
git tag
查看所有标签:
- 可用
$ git tag 版本号 提交的id
:给固定的某次提交或修改添加版本号- -a:标签名
- -m:指定说明文字
$ git show 版本号
:显示这个版本号对应提交的详细信息- 默认标签是打在最新提交的commit上的。
- 如果忘了打标签,比如,现在已经是周五了,但应该在周一打的标签没有打,怎么办?
- 方法是找到历史提交的commit id,然后打上就可以了
操作标签
- 删除本地打错的标签
$ git tag -d v0.1
- 标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:
$ git tag -d v0.9
$ git push origin :refs/tags/v0.9
:注意格式
- 推送某个标签名称对应的版本到远程
git push origin <tagname>
- 一次性推送全部尚未推送到远程的本地标签
$ git push origin --tags
git基础
https://andrewjiao.github.io/2018/12/20/git操作/