Git笔记
实践出真知。如果觉得某个命令很难理解,最好上手亲自执行该命令几次,看看究竟发生了什么变化。
git基本概念
共有三个区域:工作区、暂存区、版本库。
-
工作区 就是本地文件目录。工作区和版本库两者独立。
-
版本库 是由许多节点构成的树状结构,每个节点代表本地仓库所有文件的一个版本。
-
暂存区 是介于工作区和版本库之间的“缓冲区”。工作区借助暂存区向版本库创建新的版本(也就是节点)。
head指针 指向当前节点,head每次只会指向一个节点。
大致流程 :在 工作区 写代码,将完成的代码 add 到 暂存区 ,将暂存区的代码 commit 到 版本库 形成一个节点,将版本库的节点 push 到 云端 保存。
- 云端也有一个节点构成的树状结构。
步骤
- 做好远程仓库的准备工作。
- 创建远程仓库。
- 配置密钥。
- 做好本地仓库的准备工作。
- git init 命令初始化本地仓库。
- 连接远程仓库。
- 注意,在这一步中,务必使用 ssh 链接,如果用 https 将会卡死在输入用户名和密码这一步。实际上无论输入的用户名和密码是对是错,都会显示错误。
- git push 向远端仓库推送文档。
本地仓库准备工作
Git全局设置:
设置自己的名字和邮箱:
git config --global user.name xxx
:设置全局用户名,信息记录在 ~/.gitconfig
文件中。
git config --global user.email xxx@xxx.com
:设置全局邮箱地址,信息记录在 ~/.gitconfig
文件中。
- 执行完两个命令后会在本地家目录下看到
.config
文件,该文件保存了上述命令的名字和邮箱。 - 名字和邮箱可以随意起,但是推荐填写自己云端账号的用户名和邮箱。
创建本地仓库:
创建文件夹 : mkdir project
进入文件夹 : cd project
在 project
文件夹下执行 git init
:将当前目录配置成git仓库,信息记录在隐藏的 project/.git
文件夹中。
git remote add origin git@xxx.com:yyy/zzz.git
:将本地仓库关联到远程仓库。
此时本地仓库创建完毕。
project
是我们的本地仓库,也即工作区,后面的工作都将在该文件夹下展开。
Git本地常用命令:
基础常用命令
touch XX
:在工作区创建XX文件。
git status
:命令查看仓库状态。
- 仓库状态指:工作区的内容在修改过后:1. 是否加入了暂存区。2.是否将新版本持久化(加入版本库)。
- 文件名字变绿表示加入了暂存区。
git add xxx
:将xxx文件加入暂存区。
- 注意这里的add,不是创建文件的意思,而是将文件的修改加入的暂存区,文件的修改可以是删除文件。所有送入暂存区的信息都可以持久化。所以我们也可以将文件的删除持久化。
git add .
:将工作区 当前目录下 所有文件加入暂存区。
-
注意 :删除文件 的操作也可以同步到云端,可以用
git add -A
来将删除文件的操作添加到暂存区。 -
git add . # 添加新文件、被修改文件 git add -A # 添加新文件、被修改文件、已删除文件
git commit -m "xxx"
:将 暂存区内容 作为一个新的节点加入版本库,并将 head 指针指向该节点。
xxx
表示给自己看的备注信息,尽量用英文或者拼音,有些终端不支持中文。- commit实际上就是将暂存区持久化,所以可以只将一部分文件持久化。
恢复与删除命令
git restore XX
:将XX从暂存区的文件撤回到工作区,工作区的文件会被暂存区的文件覆盖。
- 如果暂存区没有内容,就回滚到 HEAD 指向的版本 ,常用来将写错的文件恢复到上次保存的版本。
git rm --cached XX
:会把暂存区的文件撤回到工作区,但工作区的文件不会被修改。
- 可以理解为只是撤回了暂存区的文件。
- 这个操作其实很有用处,比如在本地和云端都有一个文件
xx.md
,现在我想要在云端删除这个文件,本地保留,就可以用该命令。- 假如直接
rm xx.md
,然后上传云端,会发现云端并没有改变。
- 假如直接
git rm XX
:用于删除XX文件。
- 如果工作区和暂存区都有名字为XX的文件,那么会给出提示是否要强制删除该文件(同一执行后工作区和暂存区该文件都会消失)。
- 如果工作区中该文件已经删除但暂存区还有,那么该命令直接执行,将从暂存区中删除该文件。
git rm --cached XX
:将文件从仓库索引目录中删掉,不希望管理该文件。
总结 : git rm
更倾向于删除文件,而 git restore
更倾向于恢复工作区的文件。
rm xxx -rf
:删除本地仓库XXX。
- 如果未将本地仓库上传至云端,请谨慎执行该项。若已经将本地仓库上传至云端,误删本地仓库后可以将云端的仓库下载到本地。
查看命令
git log
:查看当前分支的所有节点。
- 说是所有,其实不准确,更准确的描述是:从根(此处的根指:最初还没有任何节点时的空)走到当前head指针指向的节点,路径上的所有节点。
- 执行
git log
命令后,要从下往上看展示的内容。 - 注意 :如果节点很多,会自动进入翻页状态。按
q
退出。
git log --pretty=oneline
:将每个版本用一行来显示,相比较 git log
好处是看起来更清爽(实际体验很棒)。
执行 git diff XX
:查看工作区的XX文件相对于暂存区修改了哪些内容。
- 如果暂存区为空,那么就比较工作区XX文件和head指针指向的版本中的XX文件。
git reflog
:查看HEAD指针的移动历史(包括被回滚的版本)。
- 如果将本地仓库删除,移动历史也会随之删除,即使从云端将仓库重新下载到本地也无法重现移动历史。
git branch
:查看所有分支和自己当前所处分支。
回滚命令
回滚:将head指针指向之前的某个版本,当前目录下的所有文件都将被修改为该版本的状态。
git reset --hard HEAD^
:将head指针往前回滚一个版本。已经存在的节点不会删掉。
- HEAD后跟几个
^
就表示往前回滚几个版本。
git reset --hard HEAD~100
:往上回滚100个版本。
git reset --hard 版本号
:回滚到某一特定版本。
- 版本号:
git log
查看版本时,每个版本哈希值的前7位。
Git云端常用命令
云端主要用于实现不同机器之间代码的同步,这为多人合作提供了基础。
注意 :尽管在本地不同分支可以共享同一个节点,但在云端,每个分支都有自己的历史节点记录,不同的分支之间不共享历史节点记录。
准备工作
在云端注册账号。
在云端创建新的仓库,注意名字要和本地仓库的名字一致。
- 谨慎选择 可见性级别 。
- 注意 :如果在本地已经有了对应仓库,在云端创建仓库的目的是为了把本地仓库上传至云端,需要 取消勾选使用自述文件初始化仓库 选项。如果没有取消勾选,请删除并重建仓库。
注意 :git是使用ssh密钥来访问的,所以如果我们要向云端仓库上传文件需要提前在云端设置ssh密钥。
- 此处以及后续所提到的
密钥
都将特指ssh公钥
。每个服务器还有自己的ssh私钥,请妥善保存。
获取服务器ssh公钥:首先查看服务器家目录下是否有 .ssh
隐藏文件夹,如果没有,执行 ssh-keygen
命令 创建密钥 。然后执行如下命令:
- 在家目录下进入
.ssh文件夹
。 - 执行
cat id_rsa.pub
命令。将该命令展示的信息复制出来(鼠标左键选中文本,按下ctrl+insert
)。- 注意,执行完
ssh-keygen
命令后,本地的.ssh
文件夹下(如果是在.ssh
文件夹下执行的该命令)会出现两个文件,分别是id_rsa
和id_rsa.pub
,从名字中可以很容易的看出前者是私钥,后者是公钥。后续每次执行 git push 操作都需要输入一次自己设置的公钥,如果想要避免如此,则将公钥中的内容,复制到~/.ssh/authorized_keys
文件里即可。 - 注意,在执行
ssh-keygen
命令 创建密钥 时,系统会提示 设置密码 ,非常建议 连续按下回车表示不主动设置密码,否则如果主动设置了例如123456
这样的密码,那么后续每次git push
时都需要手动输入这里设置的密码。
- 注意,执行完
在云端添加密钥:将复制的文本粘贴到云端 添加ssh密钥
处。通常在用户设置中可以找到。
- 在粘贴的时候请使用
ctrl+v
,使用shift+insert
会导致格式错误致使添加失败。 - 粘贴文本之后,密钥标题通常会自动填好,如果没有,请手动添加。标题:ssh密钥对应服务器的名字。
git remote add origin git@xxx.com:yyy/zzz.git
:将本地仓库关联到远程仓库。
-
xxx为云端域名,对应云端服务器的IP地址。yyy为在云端注册的账号名,zzz为云端仓库名,
yyy/zzz.git
实际上就是云端仓库在云端的目录。 -
如果在 本地仓库准备工作 环节没有执行
git init
命令,请于关联仓库之前在本地仓库根目录下执行该命令。- 例如本地仓库名为
project
,那么就在project/
下执行。
- 例如本地仓库名为
注意 :可以添加多个密钥,这样就可以使得多台服务器共用该仓库,这是多人合作开发的基础。
云端常用命令
git push -u origin master
(第一次需要-u以后不需要):将当前分支推送到远程仓库。
- 第一次执行完
git push -u origin master
后,再推送时只需要执行git push
,依旧只是将当前所在分支推送到云端。 git push origin branch_name
:将本地的某个分支推送到远程仓库。origin
通常表示云端。
git push --set-upstream origin branch_name
:设置本地的branch_name分支对应远程仓库的branch_name分支。
- 在向云端仓库推送branch_name分支时,如果云端仓库没有该分支,需要执行该命令在云端创建该分支并与本地仓库的branch_name分支对应。
- 通常用于
git push
向云端推送分支。- 注意,在使用
git push
命令时,要确保云端当前分支与本地当前分支的节点没有冲突,所谓冲突就是云端进行了修改,本地也进行了修改,那么此时同一个节点上会指向两个不同的节点(分别是云端和本地的),此时需要先执行git pull
命令将云端的操作同步到本地,在执行git push
命令。
- 注意,在使用
git branch --set-upstream-to=origin/branch_name1 branch_name2
:将远程的branch_name1分支与本地的branch_name2分支对应。
-
需要先自己在本地创建
branch_name2
分支,然后再执行该命令使其与云端branch_name1
分支对应。 -
通常用于
git pull
下载云端分支。
git pull
:将远程仓库的当前分支与本地仓库的当前分支 合并 。
-
git pull
有将云端仓库分支拉取下来,并与当前分支合并的两个含义。 -
git pull origin branch_name
:将远程仓库的branch_name分支与本地仓库的当前分支合并。
git checkout -t origin/branch_name
:将远程的branch_name分支拉取到本地。
- 使用该命令无需提前在本地创建对应分支。拉取下来的分支自动绑定云端分支,commit新节点后可以直接向云端推送。
git clone git@xxx.com:yyy/zzz.git
:将远程仓库zzz下载到当前目录下。
- 可以直接在云端仓库的首页找到对应的下载链接。
Git分支常用命令
版本库是一个由节点组成的树状结构,我们的master分支是由节点构成的一条线,称之为主分支。在主分支的任意一个节点上都可以分出一个分支,以便于我们多人合作。分支的节点也可以分出新的分支,这样就会形成一个树状结构。
注意 :
- 所有分支共用一个暂存区和工作目录,暂存区和版本库是相互独立的。当我们
commit
时,只会在当前所处分支后创建节点,其他分支将不会有任何变化。 - 不同的分支也可以共用同一个节点。
分支的创建/删除/切换
git checkout -b branch_name
:创建并切换到branch_name这个分支。
- 此时并没有创建新的节点,因为节点只能由
commit
创建,此时只是有了一个向其他分支创建节点的趋向。
git checkout branch_name
:切换到branch_name这个分支。
git branch -d branch_name
:删除branch_name分支。
-
在删除branch_name分支之前,必须先将head切换到其它分支。
-
如果在删除分支之前没有合并该分支,系统将在 删除该分支后 给出提醒。
git push -d origin branch_name
:删除 远程仓库 的branch_name分支。
合并分支
git merge branch_name
:将 branch_name分支合并到当前分支。
git merge
使用的是Fast-forward
模式,所以不会创建新的节点,只是将branch_name分支的节点合并到head所在的分支上,并根据节点的commit时间排序。 分支合并的本质是节点路径的合并 。- 分支合并是将branch_name合并到当前分支,其中隐含着主次关系。如果已经合并过一次,且此时branch_name分支和head分支路径完全相同(完全相同指branch_name分支的最新节点与head所指分支的最新节点是同一节点):
- 若branch_name分支没有任何新的节点,当head所指分支添加新的节点并再次执行
git merge branch_name
命令,则不会有任何变化,head分支上的修改也不会同步到branch_name上; - 反之branch_name分支没有任何新的节点,当head所指分支添加新的节点,切换到branch_name分支,执行
git merge head_branch_name
命令时,原来head分支的修改将会同步到branch_name分支上。 - 通过这个案例会更好的理解:分支合并的本质是节点路径的合并 这句话。
- 若branch_name分支没有任何新的节点,当head所指分支添加新的节点并再次执行
- 如果branch_name分支和head所指分支,在各自的节点路径上对同一文件各自进行了修改,那么在合并时就会产生该文件的冲突,需要自己手动解决冲突并commit新节点来持久化冲突的解决。
- 例如如果此时branch_name分支和head分支路径完全相同(完全相同指branch_name分支的最新节点与head所指分支的最新节点是同一节点,记该节点为
flag
),该节点中有文件test.txt
,branch_name分支先在该文件内添加内容aaa
并持久化,记为aaa
。之后head所指分支在test.txt
文件内添加bbb
并持久化,记为bbb
。此时若在head所指分支下执行git merge branch_name
命令,则会产生冲突,需要手动解决冲突并持久化,记为fix
。 - 那么此时head所指分支上的
flag
节点后将出现3个节点,依次是aaa
,bbb
,fix
。 - 只要没有 同时修改同一份文件 ,就不会有冲突。
- 例如如果此时branch_name分支和head分支路径完全相同(完全相同指branch_name分支的最新节点与head所指分支的最新节点是同一节点,记该节点为
- 注意 :产生冲突后如果没有手动解决冲突并commit持久化,分支合并 将会取消。
stash暂存
将某个时刻的工作区或暂存区全部内容存入到栈中。当然我们也可以直接commit持久化,这没有任何问题。stash暂存只是除此之外的一种保存工作区与暂存区状态的手段。可以多次入栈,但是入栈出栈将遵守栈的规则。
git stash
:将工作区和暂存区中尚未提交的修改存入栈中。
git stash apply
:将栈顶存储的修改恢复到当前分支,但不删除栈顶元素。
git stash pop
:将栈顶存储的修改恢复到当前分支,同时删除栈顶元素。
git stash drop
:删除栈顶存储的修改。
git stash list
:查看栈中所有元素。
Git终极秘籍
所谓大道至简,掌握这四个命令,你就已经掌握了Git 的50% 。其他命令一般只在与别人共同开发时才会用到。
git push
:将当前分支推送到远程仓库。
git pull
:将远程仓库的当前分支与本地仓库的当前分支 合并 。
git add .
:将工作区所有文件加入暂存区。
git commit -m "xxx"
:将 暂存区内容 作为一个新的节点加入版本库。