一、GIT
1.1 简单配置
git是版本控制系统,与svn不同的是git是分布式,svn是集中式
配置文件位置
# 配置文件
.git/config 当前仓库的配置文件
~/.gitconfig 全局配置文件
# 查看所有配置项
git config --list
友好的查看日志
# 设置别名
# 友好的查看日志
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 --all"
git log --decorate --oneline --graph --all
git lg
设置用户名和邮箱
# 设置用户名和邮箱
git config --global user.name "xxx"
git config --blobal user.email "[email protected]"
1.2 工作区和暂存区
工作区(Working Directory)是当前文件夹,当前文件夹下的.git文件夹是版本库(Repository)。版本库里有很多东西,其中有
- 最重要的就是暂存区(stage或index)
- Git为我们自动创建的第一个分支master
- 指向master的一个指针叫HEAD
工作区--暂存区(stage/index)--当前分支(master)--远程库
关系图
版本说明
HEAD 当前版本
HEAD^ 上一版本
HEAD^^ 上上版本
HEAD~100 往上100个版本
1.3 add/commit/diff/reset
add命令
commit命令
diff命令
reset
二、常用命令
2.1 init/add/commit/status/log
init
cd learngit
git init
# 在某目录下执行命令后,该目录会生成一个.git的隐藏文件夹,这个目录就是一个版本库了
# 所有版本控制系统只能跟踪文本文件的发动
# 如TXT文件中删除了第4行,图片等二进制文件作为一个整体
# 统一用UTF-8编码
add
# 添加一个文件到暂存区(Stage)
vi readme.txt
git add readme.txt
commit
# 将文件提交给HEAD
git commit -m 'wrote a readme file'
# 不产生新快照的提交
git commit --amend
查看状态
git status
# 通过该命令可以清楚的了解当前版本库中的文件处于什么状态
查看历史
git log
git log --pretty=oneline
git lg
# 自定义的一个别名,参照 简单设置
git reflog
# 查看执行的每一条命令
2.2 文件对比
准备
# 工作区的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 changes of files.
# 暂存区的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 changes of files by stage.
# master的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 changes.
比较工作区与暂存区中的文件
git diff -- readme.txt
比较工作区与版本库中的文件
git diff HEAD -- readme.txt
比较暂存区与版本库
git diff --cached HEAD
比较两个历史快照
git diff id1 id2
2.3 版本回退
有如下几个版本:
查看历史记录是这样的:
回退到指定版本:
git reset HEAD^/comment_id
# comment_id,ID号,前7位,可以通过git reflog和git log命令进行查看
版本库覆盖xxx
# 工作区----暂存区(stage)----版本库(HEAD)----服务器
# 三种模式soft/mixed/hard,默认是mixed
# 版本库里上一版本覆盖最新版本
git reset --soft HEAD^
# 1.移动HEAD的指向,将其指向上一个快照
# 版本库上一版本覆盖最新版本和暂存区
git reset --mixed HEAD^
# 1.移动HEAD的指向,将其指向上一个快照
# 2.将HEAD移动后指向的快照回滚到暂存区域
# 版本库上一版本覆盖最新版本和暂存区和工作区
git reset --hard HEAD^
# 1.移动HEAD的指向,将其指向上一个快照
# 2.将HEAD移动后指向的快照回滚到暂存区域
# 3.将暂存区域的文件还原到工作目录
暂存区覆盖工作区
# 暂存区的内容覆盖工作区(丢弃工作区的修改)
# 撤销工作区的修改
# 没有--,该命令就是切换分支的命令了
git checkout -- readme.txt
版本库覆盖暂存区
# 版本库的内容覆盖暂存区(丢弃暂存区的修改)
# 撤销暂存区的修改
git reset HEAD readme.txt
2.4 暂存区修改
这样一种场景:工作区,暂存区,版本库里内容一样,类似.project类似这种eclipse的项目配置文件也存在于版本控制中,现在把.project这类文件加入到忽略名单后
# 这个命令是把.project从暂存区中删除
git rm --cached .project
# 提交暂存区
git commit -m "delete .project"
2.5 删除/重命名
# 只能删除工作区和暂存区中的文件
git rm filename
# git rm readme.txt与如下两个命令等价
rm readme.txt
git add readme.txt
# 如果工作区和暂存区中的文件内容不同时,下面两个命令可把两个都删除
git rm -f filename
git rm --cached filename
# 重命名
git mv filename1 filename2
三、远程仓库
3.1 免登录设置
Windows下生成ssh-keygen
1.安装Git
2.打开Git Bash
3.输入 ssh-keygen -t rsa -C "your email"
Linux下生成ssh-key
ssh-keygen -t rsa -C "your email"
cat ~/.ssh/id_rsa.pub
# ~/.ssh/id_rsa 这是私钥
# ~/.ssh/id_rea.pub 这是公钥
# 验证
ssh -T [email protected]
3.2 远程库命令
关联远程仓库
# 把本地仓库与远程仓库相关联
git remote add origin [email protected]:yysue/learngit.git
# yysue:github账户名或gitee账户名
# origin:远程库的名字,这是Git默认的叫法
# 关联分支
git branch --set-upstream-to=origin/master master
# 将本地的master分支与远程origin库的master分支关联
# pull,第一次pull加--allow-unrelated-histories
# https://stackoverflow.com/questions/37937984/git-refusing-to-merge-unrelated-histories-on-rebase
git pull --allow-unrelated-histories
直接修改配置
# 当前版本库目录下
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "origin"]
url = [email protected]:yysue/mysqldba.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
查看远程库
git remote -v
推送到远程库
git push -u origin master
# 把本地所有内容推送到远程库上
# -u参数,不但会把本地master分支推送到远程master分支,还会把本地master分支与远程master分支相关联
# 第一次推送用-u,以后用就可以不用了
git push origin master
从远程库抓取
git pull origin master
从远程库克隆
git clone [email protected]:h2o1k/gitskills.git ssh协议,速度快
git clone https://github.com/h2o1k/gitskills.git https协议
四、分支管理
4.1 branch/checkout/merge
查看master分支
master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点
创建并切换到dev分支
# 查看当前分支的命令
git branch
git checkout -b dev
# -b 表示创建并切换,与下面两条命令等价
git branch dev
git checkout dev
# 再查看一下分支
git branch
在dev分支提交
vi dev.txt
Creating a new branch is quick.
git add dev.txt
git commit -m "add dev.txt"
切换到master分支
git checkout master
dev合并到master
git merge dev -m "merge dev"
# merge合并指定分支到当前分支,
# so,必须在master分支下执行上述命令
保留分支信息的合并
git merge --no-ff -m "merge" dev
# --no-ff会保留分支信息
通常,分支合并时,Git会用Fast forward模式,这种模式下,删除分支后,会丢失分支信息,禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息
删除dev分支
git branch -d dev
产生冲突
master分支和feature1都有新的提交
解决冲突
编辑冲突文件,然后再添加、提交、合并,最后删除分支feature1
查看日志
分支管理策略
4.2 stash
我们有时会遇到这样的情况,正在分支a上开发一半,然后分支b上发现Bug,需要马上处理。
这时候分支a上的修改怎么办呢,git add 是不行的,有的git客户端版本会提示还有add过的文件没提交不能切换分支,有的git客户端版本会把修改带到b分支。
git stash 就是解决这个问题,它把当前工作区的修改和git add的内容都保存到一个地方,然后git reset HEAD,使工作区回到上一次提交,处于干净状态。然后就可以很放心的切到另外的分支b干活了。
git stash save “先给我保存一下,我要去别的分支修bug”
git stash list
# 切换到其他分支去修改bug
# ...
# 再切换到打stash的分支
git stash pop
# git stash pop相当于执行git stash apply和git stash drop
git stash apply [email protected]{num}
4.3 rebase
有的时候我们在一个分支a开发的时候,master已经进入了很多修改,这时候如果把a的修改提交上去,可能就会跟主干有冲突,需要在主干解决冲突才能提交,这样比较难看。
这时候git rebase就有用了,git rebase BRANCH_NAME可以把BRANCH_NAME分支的修改带到当前分支来,这样当前分支就有了BRANCH_NAME分支的所有内容,这样在当前分支开发的内容提交以后不会跟BRANCH_NAME有冲突,冲突在当前分支就可以解决。
4.4 小技巧
可以取消已经提交的commit,一般我们只用git reset HEAD^。因为每个分支可能开发过程中为了保存过程以便回溯会有很多commit,但是我们要求进入主干时,每个功能和bugfix只能有一个提交,因此可以先用git reset退回到最早的commit,然后把自己的修改最后打包成一个commit,再去跟主干合并。
利用这两个命令,我们可以很好的管理我们的MySQL开发。我们只有一个master分支作为主干,不允许在主干上直接开发。每个同学根据feature和bug的issue建立分支,然后在分支上开发,不管开发过程中有多少个commit,我们要求最终提交每个bugfix或feature只能有一个提交。因此每个同学完成开发后,都需要git reset 退到最早的commit,git stash save宝存一下自己的修改,然后git checkout master; git pull拖一下最新的主干,然后返回自己的分支,再做git rebase master,把当前分支推进到主干,最后git stash pop弹出修改,有冲突则在当前分支解决,再git push。
# 此时commit id为a37b9ff,切换到开发版本dev
git checkout -b dev
# 实现了一个功能xxx,期间多次commit
...
# xxx开发完毕后,合并到主分支要求只有一个commit
git reset a37b9ff
git stash save "保存开发功能xxx的修改"
git checkout master
git pull
git checkout dev
git rebase master
git stash pop
# 处理冲突
git add .
git commit -m "功能xxx"
git checkout master
git merge --no-ff -m "merge 功能xxx" dev
4.5 常用分支命令
# 查看当前分支
git branch
# 创建分支dev
git branch dev
# 切换到分支dev
git checkout dev
# 创建并切换到分支dev
git checkout -b dev
# 合并指定分支(dev)到当前分支
git merge dev
# 删除分支dev, 如果分支有未提交的这样删除不了
git branch -d dev
# 强制删除
git branch -D dev
# 查看分支合并情况
git log --pretty=oneline --graph --abbrev-commit
# master转gh-pages
# 创建一个没有父节点的分支gh-pages
git checkout --orphan gh-pages
五、标签管理
5.1 常用标签命令
# 切换到要打标签的分支上
git branch
git checkout master
# 打标签
git tag v1.0
# 默认标签是打在最新提交的commit上,也可以指定commit id
# git log --pretty=oneline --abbrev-commit
git tag v0.9 <commit id>
# 查看标签列表
git tag
# 查看某标签信息
git show v0.9
# 标签加注释
git tag -a v0.1 -m "version 0.1 released" 2428164
# 可以用PGP签名标签
git tag -s v0.2 -m "signed version 0.2 released" fac145a
# 删除标签
git tag -d v0.1
# 把标签推送到服务器
git push origin v1.0
# 一次性推送全部尚未推送的本地标签
git push origin --tags
# 删除远程库标签
# 先删除本地标签
git tag -d v0.9
# 再删除远程库标签
git push origin :refs/tags/v0.9
六、使用GitHub
6.1 Fork/克隆
七、自定义Git
# 如果一个jar文件已经加到忽略文件里边了
# 想把一个jar文件添加到版本库
git add -f aaa.jar
八、问题
8.1 注释输入不了中文了
# Git安装目录 D:\Program Files\Git
# 编辑如下文件D:\Program Files\Git\etc\inputrc
# 确保如下行的配置如下,就可以保证输入中文注释了
set output-meta on
set convert-meta off