0.使用GitHub
0.1 添加到远程库
0.2 从远程库克隆
0.3 GitHub使用1.创建版本库
2.时光穿梭机
2.1 版本回退
2.2 工作区和暂存区
2.3 管理修改
2.4 撤销修改
2.5 删除文件3.分支管理
3.1 创建与合并分支
3.2 解决冲突
3.3 分支管理策略
3.4 Bug分支
3.5 Feature分支
3.6 多人协作4.标签管理
4.1 创建标签
4.2 操作标签5.自定义Git
5.1 忽略特殊文件
5.2 配置别名
5.3 搭建Git服务器6.扩展
6.1 rebase的使用
0.使用GitHub
生成SSH key,如果没有key的话,在用户主目录下面,执行下面语句:
ssh-keygen -t rsa -C "youremail@example.com"
该语句在用户主目录下面生成.ssh文件夹,文件夹中有两个文件,分别是id_rsa和id_rsa.pub,前者是私锁,不能告诉别人,后者是公锁,可以告诉别人,需要将后者即是id_rsa.pub中内容添加到GitHub的账户中,因为Git支持SSH协议,SSH key是GitHub用来识别代码是该用户提交过来的。
0.1 添加到远程库
git remote add origin https://github.com/Jayzen/demo_for_test.git
#远程库的名字叫做origin,是默认的远程库的名称,其中demo_for_test是用户自定义的仓库名称
git push -u origin master
#第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令
git push origin master #第二次之后远程库的代码提交(对比第一次提交少了-u 参数)
0.2 从远程库克隆
git clone https://github.com/Jayzen/gitskill.git #自己的电脑这个可行
git clone git@github.com:Jayzen/gitskill.git
0.3 GitHub使用
如果要修改一个开源库,步骤如下:
fork #fork一个项目,相当于在自己的github上面复制了一个相同的项目
git clone XX #在用户的本地复制该代码
git push #用户本地修改代码之后,推送到GiHub中用户本身的目录下面
pull request #发起这个pull request,看作者是否接受
具体示意图见如:
1.创建版本库
git init #初始化一个仓库
git add <file> #添加到仓库
git commit -m "some descriptions" #提交到仓库,其中后面显示的-m是对本次提交的一次说明
2.时光穿梭机
git status #查看用户的状态
#如果只是对代码进行了修改,之后没有做任何改动,则会显Changes not staged for commit
#如果是在当前文件夹内添加了一个文件,之后没有做任何动作,则会显示untracked files
#如果对文件进行了修改,执行了add,没有执行commit,则会显示Changes to be committed
#如果代码全部提交到仓库中,则会显示nothing to commit, working directory clean
git diff #查看代码做了哪些修改,这种状态修改的说明只能是该文件没有执行git add之前才能看到
2.1 版本回退
git log #显示从近到远的提交日志
git log --pretty=oneline #将这些日志按照行显示
git reset --hard HEAD^ #将版本退回到上一次提交,其中HEAD^表示上一个版本,HEAD^^表示上上一个版本
git reset --hard commit_id #其中commit_id是commit过程中生成的id值
git reflog #记录head指向的每一次命令
head指向append GPL
改为head指向add distributed
2.2 工作区和暂存区
工作区其实就是git当前工作的文件夹。
把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
与此同时,在工作区中修改readme.txt文件和添加LICENSE,并且两次使用add命令,结果如下所示:
以上的结果可以看出,两次add方法是将文件添加到暂存区中,执行git commit -m "fourth commit",得到以下的结果,暂存区是干净的。
2.3 管理修改
Git跟踪的是修改,而不是文件。
git commit 提交给是是暂存区的内容,如果修改了文件,没有执行commit add,那么git commit对修改的文件内容无效。
git diff HEAD -- readme.txt #查看工作区和版本库里面最新版本的区别
2.4 撤销修改
第一种情况:在工作区中修改,当时没有提交到暂存区
git checkout --file
命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:
一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
第二种情况:已经提交到暂存区
git reset HEAD file #可以把暂存区的修改撤销掉,重新放回工作区
git checkout --file #重复第一种情况
其中
git reset #命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
2.5 删除文件
当前工作区内有两个文件,分别是demo.rb和test.rb,其中在工作区中删除文件test.rb,则下面有两种情况:
#第一种:确实要删除该文件
git rm test.rb
git commit -m "remove test.rb"
自己测试了下,下面的代码也可以实现删除功能,因为版本控制跟踪的修改,而不是文件。
git add .
git commit -m "remove test.rb"
#第二种:
删除文件出现错误,因此相当于撤销修改
git checkout --test.rb #git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
3.1 创建和合并分支
git branch #查看分支
git branch <name> #创建分支
git checkout <name> #切换分支
git checkout -b <name> #创建+切换分支
git merge <name> #合并某分支到当前分支
git branch -d <name> #删除分支
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点,每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长:
当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:
3.2 解决冲突
当主分支和从分支在同一个地方进行修改了,并且进行合并之后,出现了冲突。
#生成另外一个分支,对这个分支进行修改,然后提交
git checkout -b feature
修改demo.rb中的内容
git add demo.rb
git commit -m "commit feature"
#回到master分支,对master分支进行修改,然后提交
git checkout master
修改demo.rb中的内容,并且和上一个部分修改同一个地方
git add demo.rb
git commit -m "commit master"
#对两个分支进行合并
git merge feature #出现了conflict
#修改conflict的内容,重新进行提交
git add demo.rb
git commit -m "final commit"
#上面的内容对conflict内容进行了修改,并且在master分支上进行了合并成功
#删除分支
git branch -d feature
#用图像形式显示合并
git log --graph --pretty=oneline --abbrev-commit
3.3 分支管理策略
每个人不应该在master分支上建立分支,而应该在dev分支上建立分支,每次提交应该针对dev分支,当发布版本时应该从dev分支上提交到master分支
如果按照上文的合并方式(fast forward)进行的话,如果删除了分支,就会丢失分支信息,因此这里可以采用禁用Fast forward模式,Git就会在merge时生成一个新的commit。
git checkout -b dev
修改demo.rb文件内容
git add demo.rb
git commit -m "commit dev"
#切换到master分支,禁止fast forward模式
git checkout master
git merge --no-ff -m "merge with no-ff" dev
#查看log,可以看到分支信息
git log --graph --pretty=oneline --abbrev-commit
下面图片显示分支信息:
3.4 Bug分支
Bug分支的策略是把当前的分支存储起来,然后建立bug分支,修复好之后再对当前分支进行恢复。
git status #当前分支下的内容
git stash #对当前分支进行存储
git status #当对当前分支进行存储之后,发现当前分支的status是空的
#对bug分支进行修复
git checkout master
git checkout -b bug-issue
对demo.rb文件内容进行修改
git add demo.rb
git commit -m "bug commit"
git checkout master
git merge --no-ff -m "merge bug commit" bug-issue
git status #查看工作目录是空的
git slash list #查看slash
git slash apply #恢复后,stash内容并不删除,你需要用git stash drop来删除
git stash apply stash@{0} #恢复指定的slash
git slash pop #恢复的同时把stash内容也删了
git slash list #恢复后查看slash的内容也没有了
3.5 Feature分支
如果是开发新功能,最好是新建一个分支,如果这个分支已经被合并,那么删除这个分支使用:
git branch -d feature
如果这个分支没有被合并,删除这个分支,需要用到下面的语句:
git branch -D feature
3.6 多人协作
从远程克隆仓库也是分多种情况,第一种情况是只有一个master分支的情况下:
git clone XX #远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin
git remote #origin 此代码是查看远程库的信息,远程库的默认信息是origin
git remote -v #使用-v查看远程库更为详细的信息
origin git@github.com:michaelliao/learngit.git (fetch)
origin git@github.com:michaelliao/learngit.git (push)
git push origin master #推送master分支
git push origin dev #推送dev分支
第二种情况是当远程库存在多个分支时候,使用git clone语句克隆代码,使用git branch语句只能查看master分支,为了显示其他分支,需要创建远程的origin的dev分支到本地:
git clone XX
git branch #master
#实际上被克隆的代码库有很多分支,而这里只能显示master分支
git checkout -b dev origin/dev
#使用上面的语句在本地建立dev分支,和远程库的dev分支对象起来,同时获得远程库的分支信息代码
#在dev分支上修改代码
git commit -m "add the dev"
git push origin dev #将代码推送到远程库dev分支中
第三情况是处理冲突:两个人同时写作同一个代码库,比如在feature分支上面,一个人已经作为修改,另外一个人在此人修改之前已经git clone到本地,并且在feature同一个地方做了修改,因此会出现conflict。
#已经有其他用户在feature分支上面建立test.rb文件
#下面的代码都是在本地的feature分支上进行
git add test.rb
git commit -m "add the test.rb"
git push origin feature
上面的代码出现错误,根据提示可以知道,是因为出现了代码冲突,根据提示使用git pull。
git pull #如果存在no tracking information,说明本地分支和远程分支之间的链接关系没有建立
git branch --set-upstream-to=origin/feature feature #设置feature和origin/feature的链接
git pull #出现冲突及冲突提示
#冲突解决好之后重新提交
git commit -m "conflict commit"
git push origin feature
4.标签管理
标签是版本库的一个快照,若给版本库打了一个标签,就相当于在某个时候获取一个特定时间的版本库,标签和分支不同,分支可以移动,标签不能移动。
4.1 创建标签
git checkout master #切换到最新的master分支上
git tag v1.0 #给最新的分支贴上标签
git tag #查看所有标签
默认情况下标签是打在最新的提交的commit上,如果需要打在之前提交的commit上,需要如下的语句
git log --pretty=oneline --abbrev-commit #显示commit id log
git tag v0.9 1234234 #其中1234234是commit id值,即将标签打在这个commit id中。
git show v1.0 #查看某个版本的标签
git tag -a v0.1 -m "version 0.1 released" 3628164
#创建带有说明的标签,用-a指定标签名,-m指定说明文字
4.2 操作标签
git tag -d v0.9 #删除标签
git push origin v0.9 #因为标签都是在本地的,此代码是推送标签到远程
git push origin --tags #一次性推送全部尚未推送到远程的本地标签
#如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:
#然后,从远程删除。删除命令也是push
git tag -d v0.9
git push origin :refs/tags/v0.9
5.自定义Git
git config --global color.ui true #设置颜色
5.1 忽略特殊文件
在工作区建立 .gitignore
ruby的示例文件可以在这里找到
5.2 配置别名
配置别名就是在将Git的命令用其他名字来表示,示例代码如下所示:
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
#--global参数是全局参数,也就是这些命令在这台电脑的所有Git仓库下都有用。
每个仓库的Git配置文件都放在.git/config文件中,其中别名就在[alias]后面,要删除别名,直接把对应的行删掉即可。
[core]
repositoryformatversion = 0
filemode = true bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:michaelliao/learngit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
last = log -1
而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig
中:
[alias]
co = checkout
ci = commit
br = branch
st = status
[user]
name = Your Name
email = your@email.com
5.3 搭建Git服务器
见这里
6.扩展
6.1 rebase的使用
相关文档
在master分支上简历mywork分支,示意图如下所示:
在mywork分支上提交两次代码,同时其他用户在master分支上提交了两次代码,示意图如下所示:
在这里,你可以用"pull"命令把"origin"分支上的修改拉下来并且和你的修改合并; 结果看起来就像一个新的"合并的提交",示意图如下所示:
但是,如果你想让"mywork"分支历史看起来像没有经过任何合并一样,可以用git rebase,代码如下所示:
git checkout mywork
git rebase origin
这些命令会把你的"mywork"分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把"mywork"分支更新 到最新的"origin"分支,最后把保存的这些补丁应用到"mywork"分支上。
当'mywork'分支更新之后,它会指向这些新创建的提交(commit),而那些老的提交会被丢弃。 如果运行垃圾收集命令(pruning garbage collection), 这些被丢弃的提交就会删除。
现在我们可以看一下用合并(merge)和用rebase所产生的历史的区别:
6.2 修改最近一次的提交 commit --amend
该功能会修改最近一次的提交,使用commit --amend
比如最开始是这样的:
需要对添加add的讲解进行修改,使用下面代码:
git add .
git commit --amend
上面的代码会跳出一个编辑页面,可以修改添加add的讲解的值,修改为添加add和commit的讲解,并且进行保存,使用git log操作,可以得到如下的结果:
6.3 取消最新一次的提交 git revert head
下面的代码可以取消最近一次的提交
git revert HEAD
原本最初的提交branch如下所示:
执行git revert HEAD之后,变为如下的结果
就是说针对“添加pull的讲解”所变化的内容消失了。
6.4 使用reset来删除前面的几个提交
代码如下所示:
git reset --hard HEAD~~ #这是删除最前面的两个提交
git reset --hard HEAD~ #这是删除了最前面的一个提交
git reset --hard ORGI_HEAD #如果之前的reset出错了,该代码会返回最开始进行reset的位置
图片演示如下:
6.5 **使用cherry-pick将其他分支中的内容添加到主分支中 **
如下图所示:
0.使用GitHub
0.1 添加到远程库
0.2 从远程库克隆
0.3 GitHub使用1.创建版本库
2.时光穿梭机
2.1 版本回退
2.2 工作区和暂存区
2.3 管理修改
2.4 撤销修改
2.5 删除文件3.分支管理
3.1 创建与合并分支
3.2 解决冲突
3.3 分支管理策略
3.4 Bug分支
3.5 Feature分支
3.6 多人协作4.标签管理
4.1 创建标签
4.2 操作标签5.自定义Git
5.1 忽略特殊文件
5.2 配置别名
5.3 搭建Git服务器6.扩展
6.1 rebase的使用
0.使用GitHub
生成SSH key,如果没有key的话,在用户主目录下面,执行下面语句:
ssh-keygen -t rsa -C "youremail@example.com"
该语句在用户主目录下面生成.ssh文件夹,文件夹中有两个文件,分别是id_rsa和id_rsa.pub,前者是私锁,不能告诉别人,后者是公锁,可以告诉别人,需要将后者即是id_rsa.pub中内容添加到GitHub的账户中,因为Git支持SSH协议,SSH key是GitHub用来识别代码是该用户提交过来的。
0.1 添加到远程库
git remote add origin https://github.com/Jayzen/demo_for_test.git
#远程库的名字叫做origin,是默认的远程库的名称,其中demo_for_test是用户自定义的仓库名称
git push -u origin master
#第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令
git push origin master #第二次之后远程库的代码提交(对比第一次提交少了-u 参数)
0.2 从远程库克隆
git clone https://github.com/Jayzen/gitskill.git #自己的电脑这个可行
git clone git@github.com:Jayzen/gitskill.git
0.3 GitHub使用
如果要修改一个开源库,步骤如下:
fork #fork一个项目,相当于在自己的github上面复制了一个相同的项目
git clone XX #在用户的本地复制该代码
git push #用户本地修改代码之后,推送到GiHub中用户本身的目录下面
pull request #发起这个pull request,看作者是否接受
具体示意图见如:
1.创建版本库
git init #初始化一个仓库
git add <file> #添加到仓库
git commit -m "some descriptions" #提交到仓库,其中后面显示的-m是对本次提交的一次说明
2.时光穿梭机
git status #查看用户的状态
#如果只是对代码进行了修改,之后没有做任何改动,则会显Changes not staged for commit
#如果是在当前文件夹内添加了一个文件,之后没有做任何动作,则会显示untracked files
#如果对文件进行了修改,执行了add,没有执行commit,则会显示Changes to be committed
#如果代码全部提交到仓库中,则会显示nothing to commit, working directory clean
git diff #查看代码做了哪些修改,这种状态修改的说明只能是该文件没有执行git add之前才能看到
2.1 版本回退
git log #显示从近到远的提交日志
git log --pretty=oneline #将这些日志按照行显示
git reset --hard HEAD^ #将版本退回到上一次提交,其中HEAD^表示上一个版本,HEAD^^表示上上一个版本
git reset --hard commit_id #其中commit_id是commit过程中生成的id值
git reflog #记录head指向的每一次命令
head指向append GPL
改为head指向add distributed
2.2 工作区和暂存区
工作区其实就是git当前工作的文件夹。
把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
与此同时,在工作区中修改readme.txt文件和添加LICENSE,并且两次使用add命令,结果如下所示:
以上的结果可以看出,两次add方法是将文件添加到暂存区中,执行git commit -m "fourth commit",得到以下的结果,暂存区是干净的。
2.3 管理修改
Git跟踪的是修改,而不是文件。
git commit 提交给是是暂存区的内容,如果修改了文件,没有执行commit add,那么git commit对修改的文件内容无效。
git diff HEAD -- readme.txt #查看工作区和版本库里面最新版本的区别
2.4 撤销修改
第一种情况:在工作区中修改,当时没有提交到暂存区
git checkout --file
命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:
一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
第二种情况:已经提交到暂存区
git reset HEAD file #可以把暂存区的修改撤销掉,重新放回工作区
git checkout --file #重复第一种情况
其中
git reset #命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
2.5 删除文件
当前工作区内有两个文件,分别是demo.rb和test.rb,其中在工作区中删除文件test.rb,则下面有两种情况:
#第一种:确实要删除该文件
git rm test.rb
git commit -m "remove test.rb"
自己测试了下,下面的代码也可以实现删除功能,因为版本控制跟踪的修改,而不是文件。
git add .
git commit -m "remove test.rb"
#第二种:
删除文件出现错误,因此相当于撤销修改
git checkout --test.rb #git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
3.1 创建和合并分支
git branch #查看分支
git branch <name> #创建分支
git checkout <name> #切换分支
git checkout -b <name> #创建+切换分支
git merge <name> #合并某分支到当前分支
git branch -d <name> #删除分支
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点,每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长:
当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:
3.2 解决冲突
当主分支和从分支在同一个地方进行修改了,并且进行合并之后,出现了冲突。
#生成另外一个分支,对这个分支进行修改,然后提交
git checkout -b feature
修改demo.rb中的内容
git add demo.rb
git commit -m "commit feature"
#回到master分支,对master分支进行修改,然后提交
git checkout master
修改demo.rb中的内容,并且和上一个部分修改同一个地方
git add demo.rb
git commit -m "commit master"
#对两个分支进行合并
git merge feature #出现了conflict
#修改conflict的内容,重新进行提交
git add demo.rb
git commit -m "final commit"
#上面的内容对conflict内容进行了修改,并且在master分支上进行了合并成功
#删除分支
git branch -d feature
#用图像形式显示合并
git log --graph --pretty=oneline --abbrev-commit
3.3 分支管理策略
每个人不应该在master分支上建立分支,而应该在dev分支上建立分支,每次提交应该针对dev分支,当发布版本时应该从dev分支上提交到master分支
如果按照上文的合并方式(fast forward)进行的话,如果删除了分支,就会丢失分支信息,因此这里可以采用禁用Fast forward模式,Git就会在merge时生成一个新的commit。
git checkout -b dev
修改demo.rb文件内容
git add demo.rb
git commit -m "commit dev"
#切换到master分支,禁止fast forward模式
git checkout master
git merge --no-ff -m "merge with no-ff" dev
#查看log,可以看到分支信息
git log --graph --pretty=oneline --abbrev-commit
下面图片显示分支信息:
3.4 Bug分支
Bug分支的策略是把当前的分支存储起来,然后建立bug分支,修复好之后再对当前分支进行恢复。
git status #当前分支下的内容
git stash #对当前分支进行存储
git status #当对当前分支进行存储之后,发现当前分支的status是空的
#对bug分支进行修复
git checkout master
git checkout -b bug-issue
对demo.rb文件内容进行修改
git add demo.rb
git commit -m "bug commit"
git checkout master
git merge --no-ff -m "merge bug commit" bug-issue
git status #查看工作目录是空的
git slash list #查看slash
git slash apply #恢复后,stash内容并不删除,你需要用git stash drop来删除
git stash apply stash@{0} #恢复指定的slash
git slash pop #恢复的同时把stash内容也删了
git slash list #恢复后查看slash的内容也没有了
3.5 Feature分支
如果是开发新功能,最好是新建一个分支,如果这个分支已经被合并,那么删除这个分支使用:
git branch -d feature
如果这个分支没有被合并,删除这个分支,需要用到下面的语句:
git branch -D feature
3.6 多人协作
从远程克隆仓库也是分多种情况,第一种情况是只有一个master分支的情况下:
git clone XX #远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin
git remote #origin 此代码是查看远程库的信息,远程库的默认信息是origin
git remote -v #使用-v查看远程库更为详细的信息
origin git@github.com:michaelliao/learngit.git (fetch)
origin git@github.com:michaelliao/learngit.git (push)
git push origin master #推送master分支
git push origin dev #推送dev分支
第二种情况是当远程库存在多个分支时候,使用git clone语句克隆代码,使用git branch语句只能查看master分支,为了显示其他分支,需要创建远程的origin的dev分支到本地:
git clone XX
git branch #master
#实际上被克隆的代码库有很多分支,而这里只能显示master分支
git checkout -b dev origin/dev
#使用上面的语句在本地建立dev分支,和远程库的dev分支对象起来,同时获得远程库的分支信息代码
#在dev分支上修改代码
git commit -m "add the dev"
git push origin dev #将代码推送到远程库dev分支中
第三情况是处理冲突:两个人同时写作同一个代码库,比如在feature分支上面,一个人已经作为修改,另外一个人在此人修改之前已经git clone到本地,并且在feature同一个地方做了修改,因此会出现conflict。
#已经有其他用户在feature分支上面建立test.rb文件
#下面的代码都是在本地的feature分支上进行
git add test.rb
git commit -m "add the test.rb"
git push origin feature
上面的代码出现错误,根据提示可以知道,是因为出现了代码冲突,根据提示使用git pull。
git pull #如果存在no tracking information,说明本地分支和远程分支之间的链接关系没有建立
git branch --set-upstream-to=origin/feature feature #设置feature和origin/feature的链接
git pull #出现冲突及冲突提示
#冲突解决好之后重新提交
git commit -m "conflict commit"
git push origin feature
4.标签管理
标签是版本库的一个快照,若给版本库打了一个标签,就相当于在某个时候获取一个特定时间的版本库,标签和分支不同,分支可以移动,标签不能移动。
4.1 创建标签
git checkout master #切换到最新的master分支上
git tag v1.0 #给最新的分支贴上标签
git tag #查看所有标签
默认情况下标签是打在最新的提交的commit上,如果需要打在之前提交的commit上,需要如下的语句
git log --pretty=oneline --abbrev-commit #显示commit id log
git tag v0.9 1234234 #其中1234234是commit id值,即将标签打在这个commit id中。
git show v1.0 #查看某个版本的标签
git tag -a v0.1 -m "version 0.1 released" 3628164
#创建带有说明的标签,用-a指定标签名,-m指定说明文字
4.2 操作标签
git tag -d v0.9 #删除标签
git push origin v0.9 #因为标签都是在本地的,此代码是推送标签到远程
git push origin --tags #一次性推送全部尚未推送到远程的本地标签
#如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:
#然后,从远程删除。删除命令也是push
git tag -d v0.9
git push origin :refs/tags/v0.9
5.自定义Git
git config --global color.ui true #设置颜色
5.1 忽略特殊文件
在工作区建立 .gitignore
ruby的示例文件可以在这里找到
5.2 配置别名
配置别名就是在将Git的命令用其他名字来表示,示例代码如下所示:
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
#--global参数是全局参数,也就是这些命令在这台电脑的所有Git仓库下都有用。
每个仓库的Git配置文件都放在.git/config文件中,其中别名就在[alias]后面,要删除别名,直接把对应的行删掉即可。
[core]
repositoryformatversion = 0
filemode = true bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:michaelliao/learngit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
last = log -1
而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig
中:
[alias]
co = checkout
ci = commit
br = branch
st = status
[user]
name = Your Name
email = your@email.com
5.3 搭建Git服务器
见这里
6.扩展
6.1 rebase的使用
相关文档
在master分支上简历mywork分支,示意图如下所示:
在mywork分支上提交两次代码,同时其他用户在master分支上提交了两次代码,示意图如下所示:
在这里,你可以用"pull"命令把"origin"分支上的修改拉下来并且和你的修改合并; 结果看起来就像一个新的"合并的提交",示意图如下所示:
但是,如果你想让"mywork"分支历史看起来像没有经过任何合并一样,可以用git rebase,代码如下所示:
git checkout mywork
git rebase origin
这些命令会把你的"mywork"分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把"mywork"分支更新 到最新的"origin"分支,最后把保存的这些补丁应用到"mywork"分支上。
当'mywork'分支更新之后,它会指向这些新创建的提交(commit),而那些老的提交会被丢弃。 如果运行垃圾收集命令(pruning garbage collection), 这些被丢弃的提交就会删除。
现在我们可以看一下用合并(merge)和用rebase所产生的历史的区别:
6.2 修改最近一次的提交 commit --amend
该功能会修改最近一次的提交,使用commit --amend
比如最开始是这样的:
需要对添加add的讲解进行修改,使用下面代码:
git add .
git commit --amend
上面的代码会跳出一个编辑页面,可以修改添加add的讲解的值,修改为添加add和commit的讲解,并且进行保存,使用git log操作,可以得到如下的结果:
6.3 取消最新一次的提交 git revert head
下面的代码可以取消最近一次的提交
git revert HEAD
原本最初的提交branch如下所示:
执行git revert HEAD之后,变为如下的结果
就是说针对“添加pull的讲解”所变化的内容消失了。
6.4 使用reset来删除前面的几个提交
代码如下所示:
git reset --hard HEAD~~ #这是删除最前面的两个提交
git reset --hard HEAD~ #这是删除了最前面的一个提交
git reset --hard ORGI_HEAD #如果之前的reset出错了,该代码会返回最开始进行reset的位置
图片演示如下:
6.5 **使用cherry-pick将其他分支中的内容添加到主分支中 **
如下图所示:
将添加commit的讲解添加到master分支中,代码如下所示:
git checkout master
git cherry-pick 99daed2
#下面的提示代码是正常现象,说明提交成功
error: could not apply 99daed2... commit
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
#但是如果出现冲突的话,需要添加如下的进行如下的操作
git add filename
git commit
6.6 **使用rebase -i 汇合提交 **
这是做的事情是讲master上面最近的两次进行合并,汇合为一次提交,使用的代码如下:
git rebase -i HEAD~~
#上面的代码执行之后,会有下面的代码界面出现,将第二行的pick改为squash
pick 9a54fd4 添加commit的说明
pick 0d4a808 添加pull的说明
# Rebase 326fc9f..0d4a808 onto d286baa
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#编辑保存退出,然后出现了编辑界面,编辑里面的值,该值将成为合并commit的说明
示意图如下所示:
就是将添加commit的讲解和添加pull的讲解进行合并,成为一个commit。示意图如下所示:
6.7 用rebase -i 修改提交
在这里修改添加commit的讲解
代码修改如下所示:
git rebase -i HEAD~~
将第一行的pick改为eidt,保存之后退出
pick 9a54fd4 添加commit的说明
pick 0d4a808 添加pull的说明
# Rebase 326fc9f..0d4a808 onto d286baa
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
#打开sample.txt,适当地修改“commit的讲解”部分
git add sample.txt
git commit --amend
#已经commit,但是rebase操作还没结束。若要通知这个提交的操作已经结束,请指定 --continue选项执行rebase。
git rebase --continue
6.8 把分支内容合并成一个提交,并导入到master分支
示意图如下所示:
把下面的一个分支合并成一个提交,并导入的master分支中,具体的代码如下所示:
git checkout master
git merge --squash issue1
#出现了下面的提示,说明提交成功
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
#出现下面的提示,则说明提交失败,出现了冲突
Auto-merging sample.txt
CONFLICT (content): Merge conflict in sample.txt
Squash commit -- not updating HEAD
Automatic merge failed;
fix conflicts and then commit the result.
#说明发生了冲突,修改之后进行提交
git add sample.txt
git commit
6.9使用二分法查找bug
二分法的原理
代码演示如下:
git bisect start master commit_id #master是bad点,commit_id是最开始提交点
git bisect run make test #进行了自动化测试,此代码可以测试出错误点