Git Learn
初始化/创建仓库 git init
添加(到暂存区) git add
提交(到版本库) git commit -m "注释"
查看仓库当前状态(包括修改记录和待提交项目) git status
查看修改内容difference git diff
查看提交记录 git log
$ git log
commit 29971f9f31f728dd16e5984aa584a72b64079067 (HEAD -> master)
Author: hc18220829434 <hc971545129>
Date: Thu Feb 6 18:39:21 2020 +0800
add stage
commit 48355fd105e67a6a959b4886ed5d01adef5fc68a
Author: hc18220829434 <hc971545129>
Date: Thu Feb 6 18:37:46 2020 +0800
add LICENSE
commit 7e868f2e99fc547f5407545a720c7b0472c94f70
Author: hc18220829434 <hc971545129>
Date: Thu Feb 6 17:55:35 2020 +0800
append GPL
commit caf216bdb81e62a658cda69a4fc82d9dcf2ebc9d
Author: hc18220829434 <hc971545129>
Date: Thu Feb 6 17:53:15 2020 +0800
add distributed
commit 8c0663a8d1ae412b8dcff5647cba8bc1c9740547
Author: hc18220829434 <hc971545129>
Date: Thu Feb 6 17:41:53 2020 +0800
wrote a readme file
HEAD
表示当前版本HEAD^
表示上个版本HEAD^^
表示上上个版本HEAD~100
表示第前100个版本
回退版本或把暂存区的修改回退到工作区(当用HEAD时,表示最新的版本。) git reset
$ git reset --hard HEAD^
HEAD is now at e475afc add distributed
Git
的版本回退速度非常快,因为 Git
在内部有个指向当前版本的 HEAD
指针,当回退版本的时候,Git
仅仅是把 HEAD
从指向 append GPL
:
由->append GPL 改为 ->add distributed:
┌────┐ ┌────┐
│HEAD│ │HEAD│
└────┘ └────┘
│ │
└──> ○ append GPL │ ○ append GPL
│ │ │
○ add distributed └──> ○ add distributed
│ │
○ wrote a readme file ○ wrote a readme file
查看历史命令 以便确定要回到未来的哪个版本。 git reflog
$ git reflog
e475afc HEAD@{1}: reset: moving to HEAD^
1094adb (HEAD -> master) HEAD@{2}: commit: append GPL
e475afc HEAD@{3}: commit: add distributed
eaadf4e HEAD@{4}: commit (initial): wrote a readme file
版本库
Git
的版本库里存了很多东西,其中最重要的就是称为 stage
(或者叫 index
)的暂存区,还有 Git
自动创建的第一个分支 master
,以及指向 master
的一个指针叫 HEAD
。
把文件往 Git
版本库里添加的时候,是分两步执行的:
- 第一步是用
git add
把文件添加进去,实际上就是把文件修改添加到暂存区; - 第二步是用
git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。因为创建Git
版本库时,Git
自动创建了唯一一个master
分支,所以,现在,git commit
就是往master
分支上提交更改。
撤销修改
- 场景1:当改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令
git checkout -- file
。 - 场景2:当不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步
- 第一步用命令
git reset HEAD <file>
,就回到了场景1, - 第二步按场景1操作。
- 第一步用命令
- 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。
删除文件
- 确定删除
git rm <filename>
- 误删恢复
git checkout -- <filename>
- 注意:从来没有被添加到版本库就被删除的文件,是无法恢复的!
远程仓库 Github
由于本地 Git
仓库和 GitHub
仓库之间的传输是通过 SSH
加密的,所以,需要一点设置:
- 第1步:创建
SSH Key
。在用户主目录~
下,看看有没有.ssh
目录,如果有,再看看这个目录下有没有id_rsa
和id_rsa.pub
这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell
,创建SSH Key
:
一路回车。如果一切顺利的话,可以在$ ssh-keygen -t rsa -C "myemail@example.com"
用户主目录~
里找到.ssh
目录,里面有id_rsa
和id_rsa.pub
两个文件,这两个就是SSH Key
的秘钥对,id_rsa
是私钥,不能泄露出去,id_rsa.pub
是公钥,可以放心地告诉任何人。 - 第2步:登陆
GitHub
,打开Settings”
,SSH Keys
页面,点“Add SSH Key”
,填上任意Title
,在Key
文本框里粘贴id_rsa.pub
文件的内容。
添加远程库
- 在本地
Git
仓库中
git remote add origin git@github.com:hc971545129/learngit.git
添加后,远程库的名字就是origin
,这是Git
默认的叫法。 - 把本地库的所有内容推送到远程库上
git push -u origin master
从现在起,只要本地作了提交,就可以通过命令
$ git push origin master
把本地master分支的最新修改推送至GitHub
从远程库克隆
- 先创建一个远程库,然后
git clone git@github.com:hc971545129/GitLearn.git
Git
支持多种协议,包括https
,但通过ssh
支持的原生git
协议速度最快。
分支管理
- 首先,创建
dev
分支,然后切换到dev
分支:$ 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
命令查看当前分支:$ git branch * dev master
git branch
命令会列出所有分支,当前分支前面会标一个*
号。 - 然后,就可以在
dev
分支上正常提交,比如对readme.txt
做个修改,加上一行:
Creating a new branch is quick.
- 然后提交:
$ git add readme.txt $ git commit -m "branch test" [dev 8182d5a] branch test 1 file changed, 1 insertion(+)
- 现在,
dev
分支的工作完成,就可以切换回master
分支:$ git checkout master Switched to branch 'master' Your branch is up to date with 'origin/master'. $ git branch dev * master
- 切换回
master
分支后,再查看一个readme.txt
文件,刚才添加的内容不见了!因为那个提交是在dev
分支上,而master
分支此刻的提交点并没有变:
$ cat readme.txt Git is a distributed version control system. Git is free software distributed under the GPL. Git has a mutable index called stage. Git tracks changs not files. Git tracks changes of files.
- 现在,把
dev
分支的工作成果合并到master
分支上:$ git merge dec merge: dec - not something we can merge $ git merge dev Updating 58b1240..8182d5a Fast-forward readme.txt | 1 + 1 file changed, 1 insertion(+) $ cat readme.txt Git is a distributed version control system. Git is free software distributed under the GPL. Git has a mutable index called stage. Git tracks changs not files. Git tracks changes of files. Creating a new branch is quick.
- 合并完成后,就可以放心地删除
dev
分支了:$ git branch -d dev Deleted branch dev (was 8182d5a).
- 删除后,查看
branch
,就只剩下master
分支了:$ git branch * master
- 新的
switch
命令- 创建并切换到新的
dev
分支,可以使用:
$ git switch -c dev
- 直接切换到已有的
master
分支,可以使用:
$ git switch master
- 使用新的
git switch
命令,比git checkout
要更容易理解。
- 创建并切换到新的
- 分支总结
- 查看分支:
git branch
- 创建分支:
git branch <name>
- 切换分支:
git checkout <name>
或者git switch <name>
- 创建+切换分支:
git checkout -b <name>
或者git switch -c <name>
- 合并某分支到当前分支:
git merge <name>
- 删除分支:
git branch -d <name>
- 查看分支:
解决冲突
Git
用<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容- 查看分支合并情况
git log --graph --pretty=oneline --abbrev-commit
分支管理策略
- 首先,
master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活; - 那在哪干活呢?干活都在
dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本; - 你和你的小伙伴们每个人都在
dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。 - 所以,团队合作的分支看起来就像这样:
- 合并分支时,加上
--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward
合并就看不出来曾经做过合并。$ git merge --no-ff -m "merge with no-ff" dev Merge made by the 'recursive' strategy. readme.txt | 2 ++ 1 file changed, 2 insertions(+)