金立
2021/05/20阅读:106主题:极客黑
git使用入门
写在前面
偶尔也会使用git,不过大部分就是执行一下git clone,上传blog也就是照着网上的命令打一打,出现什么错误了也不知道什么意思。对git的运行原理,如何版本控制,以及对git与github之间的操作不是很了解。
下定决心,花了点时间,学习了一个教程,记了一点点小笔记,以供自查。
教程:廖雪峰的Git教程
首发于:jqc8438.top
一、创建版本库
1.1 刚开始设置名字邮箱
安装完成后设置一个全局量,说明这个机子上的仓库都是这个人的。
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
1.2 在需要git管理的目录下使用git init
命令把这个目录变成可以管理的仓库。
$ git init
#文件夹中会出现一个.git的文件夹,用来管理仓库
1.3 新建一个文件,或者修改一个文件后
用命令git add
告诉Git,把文件添加到仓库:
$ git add readme.md
#这个文件需要添加到仓库
用命令git commit
告诉Git,把文件提交到仓库:
$ git commit -m "wrote a readme file"
##-m 命令后面写上本次操作做了啥,用于后续查看
个人感觉:在写代码的过程中,git add命令可以多次一直用,git commit最好在实现一个功能什么的之后再使用,不然会形成居多的版本,后期也不利于版本管理。
至此,已经创建好一个仓库了。
二、历史版本回溯
2.1 使用git status
命令掌握仓库当前的状态
比如说进行修改后没有add,就会提醒你还没推到仓库。

add后再git status

commit后再git status

可以看出三步情况下status不同的状态。
2.2 可以使用git diff
查看difference,修改了什么内容

这里就可以看到红色行是原来的,绿色行是改后的
2.3 使用git log
命令显示从最近到最远的提交日志(commmit次数)
使用后,可以看到每次的提交时间,以及加的备注。

这里进行了两次改变,共有三个版本。其中,最上面的是当前版本,git中一般用HEAD来表示。上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本可以写成HEAD~100
2.4 使用git reset
命令退回到上一个版本
$ git reset --hard HEAD^
HEAD is now at e475afc add distributed
git reset命令的本质是一个,Git在内部有个指向当前版本的HEAD
指针,这个指针往不同的地方指。
使用了git reset命令之后,再使用git log命令会发现原来的不见了。可以通过commit代码号找回来
$ git reset --hard 7a09ed
HEAD is now at 83b0afe append GPL
如果找不到了,可以使用git reflog
命令,git reflog
用来记录你的每一次命令,可以找到执行某一次commit的commit号
2.5 工作区和暂存区

目前文件所放置的区域就是工作区,工作区有一个隐藏目录.git
,里面装的是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
-
用 git add
把文件添加进去,实际上就是把文件修改添加到暂存区;

-
用 git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支(如果没有新建分支,那默认的分支就是git给我们默认创建的master分支)。

当不明确,目前的版本是否已经推送到分支,可以使用git diff HEAD -- readme.txt
命令可以查看工作区和版本库里面最新版本的区别
2.6 撤销修改
想要撤销修改存在三种情况。
-
已经在文件中改了,却还没有git add -
已经git add到暂存区了,还没有git commit -
已经git commit了
①已经在文件中改了,却还没有git add
-
直接手动删了相关修改即可 -
或者使用 git checkout -- file
命令可以丢弃工作区的修改
②已经git add到暂存区了,还没有git commit
分两步,第一步用命令git reset HEAD <file>
,以把暂存区的修改撤销掉(unstage),重新放回工作区。然后再进行暂存区的修改,即使用git checkout -- file
命令
③已经git commit了
直接版本回退到上一个版本,git reset --hard HEAD^
2.7 命令git rm
用于删除一个文件
如果删错了,可以使用git checkout -- test.txt
把误删的文件恢复到最新版本:
git checkout
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
三、远程仓库
可以使用git remote
命令,查看远程库的情况
3.1 配置本地和远程端的传输协议
本地Git仓库和GitHub仓库之间的传输是通过SSH加密的
本地端设置
需要创建SSH Key ssh-keygen -t rsa -C "youremail@example.com"
。之后,可以在用户主目录里找到.ssh
目录,里面有id_rsa
和id_rsa.pub
两个文件,这两个就是SSH Key的秘钥对,id_rsa
是私钥,不能泄露出去,id_rsa.pub
是公钥,可以放心地告诉任何人。
远程端设置
在github的SSH keys中添加ssh key
因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
3.2添加到远程端
在github上创建好一个新的仓库。
在本地的learngit
仓库下运行命令:
$ git remote add origin git@github.com:username/learngit.git
这个username是自己的github用户名。
添加后,远程库的名字就是origin
,这是Git默认的叫法,也可以改成别的,但是origin
这个名字一看就知道是远程库。
下一步,就可以把本地库的所有内容推送到远程库上:
$ git push -u origin master
#把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。
由于远程库是空的,我们第一次推送master
分支时,加上了-u
参数,Git不但会把本地的master
分支内容推送的远程新的master
分支,还会把本地的master
分支和远程的master
分支关联起来,在以后的推送或者拉取时就可以简化命令。
之后,只要本地做了提交,就可以通过命令,把本地master
分支的最新修改推送至GitHub
$ git push origin master
删除远程库
如果添加的时候地址写错了,或者就是想删除远程库,可以用git remote rm <name>
命令。使用前,建议先用git remote -v
查看远程库信息:
然后,根据名字删除,比如删除origin
:
$ git remote rm origin
此处的“删除”其实是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。要真正删除远程库,需要登录到GitHub,在后台页面找到删除按钮再删除。
3.3 从远程库克隆
要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone
命令克隆。
Git支持多种协议,包括https
,但ssh
协议速度最快。
四、分支管理
分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
4.1 分支的创建和合并
图的形式理解分支
master分支是主分支,事实上他是一个指针。HEAD
严格来说不是指向提交,而是指向master
,master
才是指向提交的,所以,HEAD
指向的就是当前分支。
一开始的时候,master
分支是一条线,Git用master
指向最新的提交,再用HEAD
指向master
,就能确定当前分支,以及当前分支的提交点:

现在创建一个新的分支,例如dev
时,也就是Git新建了一个指针叫dev
,指向master
相同的提交,再把HEAD
指向dev
,就表示此时的当前分支在dev
上:

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

之后,如果我们在dev
上的工作完成了,想把dev
合并到master
上。最简单的方法,就是直接把master
指向dev
的当前提交,就完成了合并:

合并完分支后,甚至可以删除dev
分支。删除dev
分支就是把dev
指针给删掉,删掉后,我们就剩下了一条master
分支:

分支的代码实现
可以将上面的步骤代码实现:
1.创建dev
分支,然后切换到dev
分支:
$ git checkout -b dev或者使用$ git switch -c dev#Switched to a new branch 'dev'#git checkout命令加上-b参数表示创建并切换
可以使用git branch
命令查看当前分支
2.对内容进行更改后add,commit。并切换回master主分支
如果这个时候查看文件,发现是修改之前的内容。因为是在master主分支上并没有进行过修改
3.把dev
分支的工作成果合并到master
分支上
$ git merge dev#git merge命令用于合并指定分支到当前分支
4.合并完成后,删除dev
分支:
git branch -d dev#Deleted branch dev
switch命令
最新版本的Git提供了新的git 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>
4.2 分支合并中的冲突
如果出现不同的分支都进行的提交,分支都往前进了,这时候合并就可能会有冲突。(比如对同一个地方做不同的更改)

这样使用合并命令后,需要手动去修改。

用
git log --graph
命令可以看到分支合并图。
最后,删除子分支。
4.3 禁用Fast forward
模式的分支合并
之前fast forward的分支合并是这样的:

禁用fast forward的分支合并是这样的:

使用的命令是
git merge --no-ff -m "merge with no-ff" dev#因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。
合并分支时,加上--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward
合并就看不出来曾经做过合并。
4.4 利用git stash
命令保存现场
暂时不想提交当前分支正在做的工作,又需要去其他分支工作。可以利用git stash
命令保存现场
git stash##该分支里的内容就被藏起来了
用git stash list
命令查看藏起来的内容
用git stash pop
,恢复的同时把stash内容也删了
4.5 多人协作
查看远程库信息,使用 git remote -v
;本地新建的分支如果不推送到远程,对其他人就是不可见的; 从本地推送分支,使用 git push origin branch-name
,如果推送失败,先用git pull
抓取远程的新提交;在本地创建和远程分支对应的分支,使用 git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致;建立本地分支和远程分支的关联,使用 git branch --set-upstream branch-name origin/branch-name
;从远程抓取分支,使用 git pull
,如果有冲突,要先处理冲突。
五、标签管理
标签也是一个指针,可以理解为commit号的简化版。比如发布不同的版本时候,可以有不同的标签。
5.1创建标签
敲命令git tag <name>
就可以打一个新标签:
$ git tag v1.0
可以用命令git tag
查看所有标签:
$ git tagv1.0
默认标签是打在最新提交的commit上的。如果想给历史commit打标签,找到历史提交的commit id,然后打上就可以了。
比方说要对某次提交打标签,它对应的commit id是f52c633
,敲入命令:
$ git tag v0.9 f52c633
还可以创建带有说明的标签,用-a
指定标签名,-m
指定说明文字:
$ git tag -a v0.1 -m "version 0.1 released" 1094adb
可以用git show <tagname>
查看标签信息
5.2 操作标签
如果标签打错了,也可以删除:
$ git tag -d v0.1
如果要推送某个标签到远程,使用命令git push origin <tagname>
:
或者,一次性推送全部尚未推送到远程的本地标签git push origin --tags
六、 Git的可配置项
6.1显示颜色
比如,让Git显示颜色,会让命令输出看起来更醒目:
$ git config --global color.ui true
6.2 配置别名
如果敲git st
就表示git status
那就简单多了,当然这种偷懒的办法我们是极力赞成的。
我们只需要敲一行命令,告诉Git,以后st
就表示status
:
$ git config --global alias.st status
当然还有别的命令可以简写,很多人都用co
表示checkout
,ci
表示commit
,br
表示branch
:
$ git config --global alias.co checkout$ git config --global alias.ci commit$ git config --global alias.br branch
配置一个git last
,让其显示最后一次提交信息:
$ git config --global alias.last 'log -1'
甚至可以把lg
配置成了:
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

就有这样的效果
七、Git的GUI工具SourceTree
SourceTree里可以add,commit等
八、vscode中git的使用
因为平时写代码还是会在一些平台上写的,每次都打开git的页面版本控制肯定会很麻烦。不过这些这些软件一般都会提供版本控制的。vscode和pycharm本身也有可以支持git。可以寻找各种帖子,有详细解释。
作者介绍