Git结构
SVN是集中式版本控制系统,版本库是集中放在中央服务器的,必须联网
Git是分布式版本控制系统,那么它就没有中央服务器的,每个人的电脑就是一个完整的版本库。只需把各自的修改推送给对方,就可以互相看到对方的修改了。
GIT架构:
remote:远程仓库;repository:本地仓库;index:暂存区
当你在一个工程文件的目录下git init
的时候,就会在该工程目录下创建.git
文件夹,这个.git
文件夹里包含暂存区、本地仓库,然后就可以在该工程目录下使用add
、push
、pull
等指令对该工程目录进行git操作。(可以写个gitignore来指定哪些不git)
所以每个需要git(分布式版本控制)的项目都可以在其工程目录下新建git仓库
Git 身份认证
本地仓库连接远程仓库进行PUSH等操作之前,需要认证身份,有两种方式:SSH协议和HTTPS协议。
SSH协议认机器(通过ssh key公私秘钥认证),HTTPS协议认账号(通过账号密码登陆远程仓库来认证)。
SSH KEY方式
使用ssh方式添加远程仓库:
# 第一次新建项目后指定本地代码关联的远程仓库地址 git remote add origin git@github.com/aisakaki/aisakaki.github.io.git
所有的git仓库都默认使用global的ssh key,存放于home目录下的
.ssh
文件夹ssh key配置一对秘钥(本地私钥,远程仓库如github放私钥),这样就本地和远程就能验证身份,通过身份认证就可以进行push pull等各种远程操作
生成ssh key(默认生成ssh-key到home/.ssh目录下):
#用ssh-keygen来生成公私钥,后面指点非对称加密算法和署名 ssh-keygen -t rsa -b 4096 -C "your_email@example.com" #可以在后面添加参数如-f C:\Users\htt20\.ssh\test\new-rsa来指定生成秘钥储存在哪个文件 #不指定就默认用户目录下的.ssh文件夹下,如果自命名又不指定路径就储存在用户根目录下 #若未用-f指定enter后,可以自己命名储存秘钥文件的名字 Generating public/private rsa key pair. #<-到这里稍等一下,别急着回车 Enter file in which to save the key (C:\Users\htt20/.ssh/id_rsa): newName-rsa #<-这就指定新公私钥储存的名字
会生成公钥
id-rsa.pub
和私钥id-rsa
,然后将公钥存放在github远程仓库配置中即可。【多ssh key怎么配置】:即“同一台主机多个git账户”,就需要
①生成多个ssh key ,②然后配置
~/.ssh/config
或~/.gitconfig
来管理③使用局部邮箱用户名配置依然是用上面ssh key生成方法,不过注意新生成ssh key不能重名(要么-f指定新生成在哪,要么自己改名)
修改
~/.ssh/config
或~/.gitconfig
文件#~.gitconfig文件内容、 #-----------------------------------------------------------------------# #git account1 Host github.com HostName github.com IdentityFile ~/.ssh/home_rsa #git account2 Host github.com HostName github.com IdentityFile ~/.ssh/lab_rsa
私钥位置记录在config中,公钥都记录在远程仓库配置中。写了配置,多ssh key就可以生效了。
具体不同的git使用哪个ssh,是在添加远程仓库语句:
git remote add origin git@github.com/aisakaki/aisakaki.github.io.git
中绑定的。如果配置过global邮箱和用户名,就必须先取消
# 取消全局邮箱和账户名配置 git config --global --unset user.name git config --global --unset user.email # 在每个项目目录,新建仓库的时候,单独使用局部配置,不指定global参数 git init git config user.name "aisaka_home" git config user.email aisaka_home@gmail.com
ssh key和depoly key的区别:ssh keys拥有最高权限,可以管理所有仓库(项目);depoly key是这个仓库的专有key,只能操作这个项目
一样在本地创建公私钥,然后ssh key的话是将公钥添加在github账号设置里,而depoly key是添加在项目仓库的设置里
HTTPS方式
使用https方式添加远程仓库:
#和ssh方式区别在于后面url不同
git remote add origin https://github.com/aisakaki/aisakaki.github.io.git
连接远程仓库的时候,输入账号和密码登陆远程仓库(就是github的账号密码),省去了本地配置的麻烦,只要有URL和相应的权限便能进行相应的操作。但每次连接都要输入账号密码。
可以参考git http/https方式储存密码来记住账户密码
windows有GUI的git,如果使用HTTP方式会记住并自动输入github的账号密码进行认证
HTTPS方式只能public
GIT配置&操作流程步骤(SSH方式)
HTTPS方式就不需要配置SSH KEY,并且制定远程仓库的url的协议标识修改一下
配置ssh key
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
单ssh key情况,多情况需要建立多个并写config
新建远程仓库并配置ssh公钥
github网页上进行
设置全局邮箱和用户名(如果需要)
git config --global user.name "Your Name" git config --global user.email "email@example.com"
新建本地仓库
======从这里开始的操作就是在项目文件夹目录下进行操作了======
#进入目标项目的文件夹 git init
设置局部邮箱和用户名(如果需要,多ssh key情况)
git config user.name "Your Name" git config user.email "email@example.com"
clone项目到本地(如果需要。注意这里要先init,再clone)
git clone https://github.com/aisakaki/aisakaki.github.io.git
添加远程仓库
# 添加远程仓库 git remote add origin git@github.com/aisakaki/aisakaki.github.io.git
【origin】:
origin
是一个名字,它是在你clone一个托管在Github上代码库时,git为你默认创建的指向这个远程代码库的标签。你也可以改名叫其它名字,比如aisakagit,都OK的,下面你用这个仓库的时候就用aisakagit你取的别名【这个
origin
就是远程仓库git@github.com/aisakaki/aisakaki.github.io.git
的别名】开始各种GIT操作
P.S. 邮箱和用户名
为什么git需要配置邮箱和用户名呢?因为远程仓库里需要记录提交记录是由谁来完成的,只是个署名,这里的邮箱和用户名并没有身份验证作用!。
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
# (多ssh key情况不能带上global参数)
origin&master
远程仓库名字 “origin” 与分支名字 “master” 一样,在 Git 中并没有任何特别的含义,原因仅仅是它的广泛使用。
origin
是当你运行 git clone
时默认的【远程仓库】名字。 如果你运行 git clone -o booyah
,那么你默认的远程分支名字将会是 booyah/master
。
master
是当你运行 git init
时默认的【起始分支】名字
所以master
就是local branch(本地仓库默认分支),origin/master
是remote branch(远程仓库默认分支)
默认分支即主分支
#eg,这里就用了默认仓库别名origin和默认主分支名master
git remote add origin 远程仓库url #origin你改成其它的名字也是OK的,下面push的origin跟着改
git push -u origin master
P.S.后面<远程仓库别名(默认origin)>写得太累赘了,可以直接看作origin,因为一般都是取origin的
分支
分支是什么?分支就相当于是一个原来完整代码的一个副本,完全由你自己独占,修改当前分支不会影响另一个分支,就像一个平行宇宙一样(但git的分支实现方式并不是直接复制一份,而是版本组成一颗多叉树,见下)。
默认分支是主分支master,主分支是init git 的时候就默认创建的。
分支有什么用?当你修改完后,可以选择将此分支再合并到原分支(这样一来就方便管理和修改,也避免了如果在原分支上修改,修改了一半push之后别人没法使用,因为代码没写完)
GIT分支实现原理:git分支的理解
实际上,git的操作会构成一个版本链(每commit提交一次,就生成一个版本,会记录修改),分支实现的实质是指向版本链上的指针,默认分支master即是指向版本链上的master指针(见上文理解)那么在进行git操作的时候,版本链新增一个版本,然后当前分支下的分支指针后移,如果多个分支都被修改,那就会出现分叉了
【不同分支的版本链组成了一个多叉树,分支指针指向当前分支的最新版本】。分叉口即为分支修改出现不同的地方,如果仅仅是修改了一个分支,那是不会分叉出去的,原未被修改的分支还是指向原来新分支之前那个版本链位置,这时候的分支合并即为快速合并:直接将master指针指向当前分支指针位置。如果两个分支都修改了,那么git就会尝试将各自的修改合并起来(合并两个版本),如果出现冲突,那就需要手动解决冲突。
HEAD指针指向当前版本
GIT操作详解
重点记忆加粗命令
本地基本操作
暂存(add)
git add file git add .
提交(commit)
git commit # 注释换行,单引号开始结束 git commit -m ' > line1 > line2 > line3 '
可以多次向暂存区add,commit则是一次将暂存区所有内容提交到仓库
查看操作记录
# 查看所有已提交的版本信息 git log # commit后跟的就是commit-id # 还有其它相关信息比如日期、提交注释等 # 可以查看所有分支的所有操作记录(包括已经被删除的 commit 记录和 reset 的操作,结合下面reset指令可以撤销回退) git reflog
回退到某个版本
可以回退到老版本(查log),也可以回退到新版本(查reflog)
git reset --hard <commit-id>
查看文件状态(是否跟踪)
跟踪指的是commit提交的时候会提交这些add的文件,实际上就是查看暂存区哪些文件被add了。和本地分支跟踪远程分支的跟踪不是一个意思
git status # 被跟踪:tracked # 未被跟踪:untracked # 忽略:ignored,即.gitignore下的
撤销add
git reset HEAD 撤销上一次add的所有文件 git reset HEAD file 撤销file
放弃修改
放弃未暂存(add),未提交(commit)的修改
# 放弃单个文件的修改 git checkout filename # 放弃当前目录下的修改 git checkout .
分支操作
创建分支
git branch newBranch
切换分支
# 切换本地分支 git checkout newBranch
查看分支
# 本地 git branch # 本地分支及追踪的远程分支 # 所谓本地追踪的远程分支,就是push -u指定的本地分支对应远程分支的关系,或者创建并切换远程分支指定的 git branch -vv # 远程 git branch -r # 本地+远程 git branch -a
带星号的是当前所处分支
合并分支
git merge newBranch
git merge合并当前分支到master分支上
如果master分支未修改,那么执行的是快速合并,见上分支一节
如果两个分支都修改了,那么git将试图合并两个版本
如果合并两个版本的时候发生冲突,就需要手动处理冲突
删除分支
git branch -d newBranch
创建并切换分支(12合并写法)
# 本地 git checkout -b newBranch # 远程:将远程分支拉到本地的一个新分支 git checkout -b newBranch 仓库别名(一般origin)/远程分支名 # 经过这个命令之后,会形成本地分支-远程分支的追踪关系
重命名分支
git branch -m oldName newName
查看本地分支与远程分支差异
git diff --stat <localBranch> <远程仓库别名(默认origin)>/<remoteBranch>
远程操作
推送(push)
# 将本地分支推送到远程 【-u表示默认,下一次推送就会默认使用后面的参数】 git push -u <远程仓库别名(默认origin)> <本地分支名>:<远程分支名> # 经过这个命令之后,会形成本地分支-远程分支的追踪关系 eg: git push -u origin master:master #这里本地和远程分支都是默认的master #【第一次push使用-u之后就建立了跟踪关系,以后再推送就只需要如下简写,就会默认采用之前的设置】 git push
拉取并合并(pull)
pull=fetch+merge
git pull <远程仓库别名(默认origin)> <远程分支名>
拉取(fetch)(不合并)
git fetch <远程仓库别名(默认origin)> <远程分支名>
重新设定远程仓库(仓库级别):
# 当代码库远程迁移后,重新设定本地代码关联的远程地址 git remote set-url origin git@github.com/aisakaki/aisakaki.github.io.git
添加远程地址(仓库级别)
git remote add <远程仓库别名(默认origin)> <url(https方式 or ssh方式)>
删除本地指定的远程地址(仓库级别)
git remote remove <远程仓库别名(默认origin)>
查看远程仓库信息
# 列出远程分支 git remote # 列出远程分支详细信息,在每一个名字后面列出其远程url git remote -v # 更详细了。。 git remote -vv
GITHUB设置分支PUSH权限
① 管理员身份登录GitHub,找到项目
②Settings—>Branches—>Protected branches—->Choose a branch… ,选择需要保护的分支,然后点击edit按钮,
③Branch protection for 所选的分支名 —> 勾选Restrict who can push to this branch People and teams with push access
若不选择任何人,则任何人都没有push代码到该分支的权限。测试链接(git方式)
测试本地的私钥能否与我账户中的公钥认证
ssh -T git@github.com
常见GIT指令的选项参数
-d
--delete:删除
-D
--delete --force的快捷键
-f
--force:强制
-m
--move:移动或重命名
-M
--move --force的快捷键
-r
--remote:远程
-a
--all:所有
操作习惯
一般我们Git提交都不会直接提交主分支master,先提交到dev分支,没问题,再会合并到master分支。
可以写.gitignore
来让git忽略某些文件
常见分支设定:
Production分支(主线分支用于发版,不会直接改)
Develop分支(开发分支)
Feature分支(新功能分支)
Release分支(偏向测试)
Hotfix分支(紧急bug发布)
底层原理【待更新】
暂存区实际上是索引,所以才说是跟踪
P.S. 有些打了<>有些忘打了不要在意细节