赞
踩
mkdir demo
cd demo
git init
其他参数
--initial-branch 自定义初始化的分支,不一定是master
--bare 创建一个裸仓库(纯git目录 没有工作目录)
--template 可以通过模板来创建预先构建好的自定义git目录
工作区和暂存区
工作区就是本地目录(除了.git
的隐藏目录),而我们所说的暂存区就在.git
文件夹里面,常用的命令git add
命令就是把文件提交到版本库中,go commit
就是把暂存区的内容合并到当前分支上。
关于.git
目录,我们可以通过tree .git
来查看具体的内容是什么:
蓝色标识的是文件夹,可以进一步用tree
来展开;
接下来,我们可以具体来看看其中具体的文件里面的内容是什么:
cat .git/HEAD
可以看到HEAD文件的内容就是HEAD指针(当前指针)指向的分支是那一条,这里就是指向master分支
接下来,我们再通过以下命令来添加远程仓库
git remote add origin-ssh git@github.com:git/git.git
git remote add origin-http https://github.com/git/git.git
查看下远程仓库的情况,检查是否添加成功
git remote -v
也就是说我们可以对上面的仓库进行fetch/pull和push的操作了
添加后,我们再打开刚刚.git
文件夹里的config
配置文件
cat .git/config
可以看到config
文件里已经有了远程仓库的信息
如果仓库名字错了,要修改也可以通过
git remote rename <old> <new>
来修改,更多的操作请按照git remote -h
来查阅
如果我们想给同一个Origin设置不同的push
和Fetch
URL怎么办呢?可以通过下面的语句来自定义push
和Fetch
的URL
git remote add origin git@github.com:git/git.git
git remote set-url --add --push origin git@github.com:my_repo/git.git
上面的第一句是正常的添加远程仓库,仓库名为origin
,下面这一句就是把origin
仓库下的push
的URL进行了修改,调用git remote -v
结果如下:
很多人会有这样的问题,我配置了Git后,为什么还是不能从远程仓库中拉取代码?其中的一个原因,就是没有配免密认证。
HTTP Remote
URL格式: https://github.com/git/git.git
免密配置的方法:
内存:git config --global credential.helper 'cache --timeput=3600'
硬盘:git config --global credential.helper "store --file /path/to/credential-file"
不指定目录的情况下,默认是~/.git-credentials
但是http协议下的数据传输并不安全,传输双方用同一套密钥来解密数据,所以更多用采用公私钥加密的SSH来进行传输
SSH Remote
URL格式:git@github.com:git/git.git
免密配置:
SSH可以通过公私钥的机制,讲生成的公钥放在服务端,从而实现免密访问,如果是用github的话就是把自己的公钥放在github上
目前使用的Key的类型四种,分别是dsa, rsa, ecdsa, ed25519;默认使用的是rsa,由于一些安全问题,现在已经不推荐使用dsa和rsa了,所以有的时候如果自己明明配置了SSH免密认证,仍然拉取不到的话,有可能是因为服务端默认拒绝dsa和rsa,这个时候改成ed25519就行
生成ed25519的方法如下:
ssh-keygen -t ed25519 -C "you_email@example.com"
最后在 ~/.ssh(默认路径)下就能看到id_ed25519
的私钥和id_ed25519.pub
的公钥,我们把公钥的内容上传到github上就行(具体上传的方法自行百度/Google)
我们通过下列命令生成readme文件,并添加到暂存库中
touch readme.txt
vim readme.txt // 输入hello world
git add .
先通过git status
查看下git的状态
这时再通过tree .git
查看目录变化
我们可以到objects下多了个条信息
我们可以用下面的命令来查看这条信息是啥
git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
说明这条信息存的就是刚刚提交到暂存库的readme.txt文件的内容
然后再用下面的命令把暂存库的内容提交到当前分支(master)上
git commit -m "add readme"
此时的.git
目录又多了两条信息
我们可以依次用cat-file -p
来查看具体的内容
可以看到这里提到的是刚刚commit的人的信息和comment:add readme,可以猜设是commit的信息
为了验证,我们用git log
来看看commit的信息
可以发现,那串字符就是刚刚commit的id,对于那条信息内还有一条内容tree: …,可以发现后面的字符就是commit后.git文件夹的新增的另一条信息
用同样的命令查看:
这条信息里blob后面跟着的那串字符就是第一次add后的.git文件夹里新增的信息, 对应的也是相应的文件名readme.txt
讲到这里,我们可以引出git的三个比较重要的Object模型
如何把这三个信息串联在一起呢,其实我们刚刚就是顺着这条路下来的:
git log
来得到下面这张图展现的更为清晰:
在上面commit后,我们也能发现.git
目录的refs/heads
目录下多了个分支名master
通过cat
命令查看:
可以发现内容就是master分支上commit的id号
用下面的命令切换到一个新分支test
git checkout -b test
此时heads目录下多了test分支的信息
即refs的内容就是对应Commit ID,因此把ref当作指针,指向对应的Commit就表示当前ref的版本;
refs/head
前缀表示的是分支,ref/tag
前缀表示的是标签
Branch:
git checkout -b 可以创建一个新分支,新分支一般用于开发阶段,可以不断添加commit进行迭代的
Tag:
标签一般表示一个稳定的版本,例如v0.0.1;指向的commit一般不会变更,通过git tag命令生成tag
通过git tag v0.0.1
的命令后,.git
目录变化如下
通过cat
查看信息:
同样指向当前分支上最新的commit ID,即把这次commit的版本作为tag为v0.0.1的版本
我们还可以给标签添加备注:
git tag -a v0.0.2 -m "my add feature 1"
此时.git
目录下的refs/tag
下会新增v0.0.2
的文件,查看信息发现不是当前分支最新的commit ID,而这串字符也新增在Objects下,说明这是一个Object
用cat-file -p
查看后:
可以发现这里存的就是标签备注的内容,创作者,以及tag对应的commit ID
在Ref里讲到,通过Ref指针,我们可以获取当前分支的最新版本,而在object里面,如果在第一次commit后对文件修改又commit的话(通过commit的串联),那么此时此时commit ID的信息里就会多一个parent
字段,就是上一个commit版本
commit -amend
:通过这个命令可以修改最近一次的commit信息,修改后commit id会变
修改后生成一个新的commit id,并且ref指针对应的分支也会指向修改后的,但是原先的commit 信息还会在objects里面,不会被删除
rebase:通过git rebase -i HEAD~3
可以实现对最近三个commit的修改,可以的修改如下:
filter - branch
该命令可以指定删除所有提交中的某个文件或者全局修改邮箱等操作
刚刚修改历史版本部分提到,通过commit -amend
修改后原先的commit object没有被删除,但是又没有ref指向它,那么它就变成了悬空的object,也就是没有意义,会浪费仓库的体积
可以通过下面的命令来检查仓库内悬空的Object的情况
git fsck --lost--found
dangling commit后面的字符就是悬空的object的ID
这时我们可以通过git gc
命令来删除一些不需要的object,以及会对object进行一些打包压缩来减少仓库的体积。Reflog是用来记录操作日志,防止误操作后数据丢失,通过reflog来找到丢失的数据,这里我们在执行git gc
前,需要手动设置日志为过期;通过还要设置prune=now
,指定修剪多久之前的对象,默认是两周前
git reflog expire --expire=now --all
git gc --prune=now
可以通过tree .git
来查看修剪的结果
Clone
拉取完整的仓库到本地目录,可以指定分支和深度
Fetch
将远端某些分支最新代码拉取到本地,不会执行merge操作,会修改refs/remote
内的分支信息,如果需要和本地代码合并需要手动操作
这也是为什么经常有人Fetch了远端分支,发现自己本地的分支没有变化,Fetch这会把代码拉取到本地的远端分支,但不会合并到当前分支
Pull
拉取远端某分支,并和本地代码合并,操作相当于git fetch
+ git merge
,也可以通过git pull --rebase
来完成git fetch
+ git rebase
操作,可能存在冲突需要解决
把本地分支上的代码同步到远程仓库中
常用命令
一般使用git push <remote repository> <local repositoty>
例如:
git push origin master
意思把master分支上的代码同步到origin远程仓库中
假设我们已经在github上新建了一个repositoty,通过通过ssh clone到了本地,并且认为此时的master分支为工作中的主分支,那么我们touch一个readme,通过add-commit-push到远程仓库,此时我们刷新github可以看到刚刚push上来的readme文件
回到本地,我们新建一个分支feature,feature分支就用了模拟平常团队开发时,其他人的一个开发分支
git checkout -b feature
在这个分支上,他人可以对feature进行修改,然后通过add-commit-push上传到远程仓库
注意这里的push的本地repositoty是feature branch,而不是master
git push origin feature
因为github上默认了第一次push上来的branch为defalut 主分支,那么后续其他推送的分支,github上都会有提示有新的分支推送,这时创建feature分支的人可以创建一个feature到master的Pull Request (PR),repositoty的owner可以在pull request界面执行CI / CA / CR等操作(通常由另一个人来进行code review),确认无误后就可以进行merge操作,将feature分支的内容和master分支内容进行一个合并。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。