学习笔记:插图如果侵权请联系博主删除。
1.什么是分支?
开发软件时,可能有多个人同时为同一个人软件开发功能或修复BUG,可能存在多个Release版本,并且需要对各个版本进行维护。
Git分支功能可以支持同时进行多个功能的开发和版本管理。
分支是为了将修改记录的整体流程分叉保存。分叉后的分支不受其他分支的影响,可以在同一个数据库里可以进行同时进行多个修改。
可以同时进行:发布版本的历史记录,添加功能的历史记录,修复错误的历史记录
分叉的分支可以进行合并
为了不受其他开发人员的影响,可以在主分支上建立自己专用的分支。
完成工作后,将自己分支上的修改合并到主分支,
因为每一次提交的历史记录都会被保存,所以当发生问题时,定位和修改造成问题的提交就容易多了。
添加新功能,修改显示动画的错误,添加任务栏,导入各自的分支,然后进行合体。
2.master分支
在数据库进行最初的提交后,Git会建立一个名为master的分支。因此之后的提交,在切换分支之前都会添加到master分支里
3.分支的运用
Git里面可以自由的建立分支,运用规则才可以有效利用分支,介绍两种分支:Merge分支,Topic分支的运用规则。
3.1Merge分支
Merge分支为了可以随时发布release而建立的分支,它还能作为Topic分支的源分支使用,保持分支的稳定状态,如果需要进行更改,通常需要先创建Topic分支,针对该分支,可以使用Jenkins类的工具进行自动化编译以及测试。
通常会将master当作Merge分支使用。
3.2 Topic分支
Topic分支是为了开发新功能或修复Bug等任务而建立的分支。
如果需要同时进行多个任务,需要创建多个Topic分支。
Topic分支是从稳定的Merge分支创建的。完成作业后,要把Topic分支合并回Merge分支
4.分支的切换
如果需要进行切换作业的分支,就需要进行checkout操作。进行checkout时,git会从工作树还原向目标分支提交的修改内容,checkout之后的提交记录将被追加到目标分支。
4.1HEAD
HEAD指向的是现在使用的分支的最后一次更新。通常指向master分支的最后一次更新,通过移动HEAD,可以变更使用的分支。
4.2stash
未提交的修改内容以及新添加的文件,留在索引区域或工作树的情况下切换到其他分支,修改内容会从原来的分支移动到目标分支。
如果checkout的目标分支中相同的文件也有修改,checkout会失败的。
可以先提交修改内容,或者使用stash暂时保存工作树和索引里还没提交的修改内容,可以事后再取出暂存的修改,应用到原先的分支或其他的分支上
5.分支的合并
完成作业后的topic分支,最后要合并回merge分支。
合并分支有2种方法
使用merge或rebase,使用这两种方法,合并后的分支的历史记录会有很大的差别。
5.1merge
使用merge可以合并多个历史记录的流程
如bugfix分支是从master分支分叉出来的
合并bugfix分支到master分支时,如果master分支的状态没有被更改过,那么这个合并是非常简单的。
***bugfix分支的历史记录包含master分支所有的历史记录,所以通过把master分支的位置移动到bugfix的最新分支上,Git就会合并。这样的合并被称为fast-forward(快进)合并
master分支的历史记录有可能在bugfix分支分叉出去后有新的更新。
需要将master分支的修改内容和bugfix分支的修改内容汇合起来。
合并后的两个修改会生成一个提交。master分分支的HEAD会移动到该提交上。
5.2 rebase
跟merge的例子应用,进行bugfix分支是从master分支分叉出来的。
使用rebase方法进行分支合并,出现下面显示的历史记录。
流程:rebase bugfix分支到master分支,bugfix分支的历史记录会添加在master分支的后面,历史记录成一条线。
移动提交X,Y可能会发生冲突,需要修改各自的提交时发生冲突的部分。
rebase后,master的HEAD位置不变,因此,需要合并master分支和bugfix分支,即是将master的HEAD移动到bugfix的HEAD里。
6.topic分支和merge分支的运用实例
实例进行讲解topic分支和merge分支的操作方法
如需要在开发功能的topic分支操作途中,需要修改bug
如果这时候merge分支还是处于开发功能之前的状态,那么在这里新建修改错误用的主题分支,可以从开发功能的作业独立出来,以便于开始新的工作
完成bug修正工作后,把分支导入到原本的merge分支就可以公开了
回到原本的分支继续进行开发功能的操作
如果需要继续进行操作,发现需要之前修正bug时提交X的内容。
可以选择2种导入X内容的方法,一种是直接merge,另一种是和rebase导入提交X的合并分支
rebase合并分支
导入提交X的内容的状态下继续进行开发功能,有效利用了分支同时进行不同的作业
7.操作分支
7.1事前预备
建立一个新的目录 ,并且在里面建立一个空的数据库。这里我们创建一个名为tutorial的目录。
mkdir tutorial
cd tutorial
git init
Initialized empty Git repository in
在tutorial目录创建一个名为myfile.txt的档案,然后提交。
git add myfile.txt
git commit -m "first commit"
[master (root-commit) a73ae49] first commit 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 myfile.txt
l历史记录
7.2 建立分支
创建名为issue1的分支
通过branch命令来创建分支
git branch <branchname>
创建名为issue1的分支。
git branch issue1
不指定参数直接执行branch命令的话,可以显示分支列表。前面含有*的就是现在的分支。
git branch
issue1
*master
目前的历史记录
7.3 切换分支
如果需要在新建的issue1分支进行提交,我们需要进行切换到issue1分支。
要执行checkout命令以退出分支
git checkout issue1
Switched to branch 'issue1'
目前历史记录
创建分支并且进行切换
git checkout -b <branch>
切换到issue1分支的状态下提交,历史记录会被记录到issue1分支。在myfile.txt
添加add命令的说明后进行提交
add 把变更录入到索引中
git add myfile.txt
git commit -m "添加add的说明"
[issue1 b2b23c4] 添加add的说明 1 files changed, 1 insertions(+), 0 deletions(-)
目前历史记录:
7.4合并分支
向master分支合并issue1分支的修改
执行merge命令以合并分支
git merge <commit>
将指定分支导入到HEAD指定的分支,先切换master分支,然后将issue1分支导入到master分支里面
git checkout master
Switched to branch 'master'
打开myfile.txt档案以确认内容,然后提交。
在issue1分支进行了编辑上一页的档案,所以master分支的myfie.txt的内容没有更改
git merge issue1
Updating 1257027..b2b23c4 Fast-forward myfile.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
master分支指向的提交移动到和issue1同样的位置。属于fast-forward(快进)合并
打开myfile.txt档案,确认内容
add 把变更录入到索引中
7.5删除分支
既然issue1分支的内容已经顺利地合并到了master分支,可以进行删除了
在branch命令指定-d选项执行,以删除分支
git branch -d <branchname>
执行以下命令以删除issue1分支
git branch -d issue1
Deleted branch issue1 (was b2b23c4).
issue1分支被删除了。可以采用branch命令确认分支是否被删除。
git branch
7.6 并行操作
创建2个分支进行并行操作
创建:issue2,issue3分支,并且进行切换 issue2分支
git branch issue2
git branch issue3
git checkout issue2
Switched to branch 'issue2' $ git branch * issue2 issue3 master
在issue2分支的myfile.txt添加commit命令的说明后提交。
add 把变更录入到索引里面
commit 记录索引状态
git add myfile.txt
git commit -m "添加commit的说明"
[issue2 8f7aa27] 添加commit的说明 1 files changed, 2 insertions(+), 0 deletions(-)
然后进行切换到issue3分支
git checkout issue3
Switched to branch 'issue3'
打开myfile.txt档案。
由于在issue2分支添加commit命令的说明,所以issue3分支的myfile.txt里只有add命令的说明。
添加pull命令的说明后提交。
add 把变更录入到数据库里面
pull 取得远程数据库的内容
git add myfile.txt
git commit -m "添加pull的说明"
[issue3 e5f91ac] 添加pull的说明 1 files changed, 2 insertions(+), 0 deletions(-)
实现了commit和添加pull的操作并行进行
7.7 解决合并的冲突
将issue2分支和issue3分支的修改合并到master。
切换master分支后,与issue2分支合并
git checkout master
Switched to branch 'master'
git merge issue2
Updating b2b23c4..8f7aa27 Fast-forward myfile.txt | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
继续进行合并issue3分支。
git merge issue3
Auto-merging myfile.txt CONFLICT (content): Merge conflict in myfile.txt Automatic merge failed; fix conflicts and then commit the result.
产生问题:自动合并失败。由于在同一行进行了修改,所以产生了冲突。myfile.txt内容
add 把变更录入到索引中 <<<<<<< HEAD commit 记录索引的状态 ======= pull 取得远端数据库的内容 >>>>>>> issue3
在发生冲突的地方,Git生成了内容的差异,做出了修改
add 把变更录入到索引中 commit 记录索引的状态 pull 取得远端数据库的内容
修改完冲突的地方后,重新提交
git add myfile.txt
git commit -m "合并issue3分支"
# On branch master nothing to commit (working directory clean)
历史记录,因为进行了合并修改冲突部分,所以会重新创建合并修改的提交记录。
(non fast -forward)合并
7.8 用rebase合并
合并issue3分支时候,使用rebase可以使提交的历史显得更加的简洁
现在取消刚才的合并
git reset --hard HEAD~
切换到issue3分支后,对master执行rebase
git checkout issue3
Switched to branch 'issue3'
git rebase master
First, rewinding head to replay your work on top of it... Applying: 添加pull的说明 Using index info to reconstruct a base tree... <stdin>:13: new blank line at EOF. + warning: 1 line adds whitespace errors. Falling back to patching base and 3-way merge... Auto-merging myfile.txt CONFLICT (content): Merge conflict in myfile.txt Failed to merge in the changes. Patch failed at 0001 添加pull的说明 When you have resolved this problem run "git rebase --continue". If you would prefer to skip this patch, instead run "git rebase --skip". To check out the original branch and stop rebasing run "git rebase --abort".
和merge时的操作一样,修改在myfile.txt发生冲突的部分
add 把变更录入到索引中 <<<<<<< HEAD commit 记录索引的状态 ======= pull 取得远端数据库的内容 >>>>>>> issue3
rebase时候,修改冲突后的提交不是使用commit命令,二十执行rebase命令指定 --continue选项 ,如果需要取消rebase,指定 --abort选项。
git add myfile.txt
git rebase --continue
这样,在master分支的issue3分支就可以fast-forward合并了。切换到master分支后进行合并
git checkout master
Switched to branch 'master'
git merge issue3
Updating 8f7aa27..96a0ff0 Fast-forward myfile.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
最后myfile.txt的最终内容和merge是一样的,但是历史记录:
8.远程数据库
8.1 pull
执行pull可以取得远程数据库的历史记录,下面进行数据库提交的讲解
确认更新的本地数据库分支没有任何修改
只进行fast-forward合并,图中的master是本地数据库的master分支,
orign/master是远程数据库的orign的master分支
如果本地数据库的master分支有新的历史记录,就需要合并双方的修改。
执行pull就可以进行合并,如果没有冲突的修改,就会自动创建合并提交。
如果发生冲突,先解决冲突,在进行手动提交
8.2fetch
执行pull ,远程数据库的内容会进行自动合并,但是有时候只是想确认本地数据库的内容而不是合并,则会进行fetch
执行fetch 就可以取得远程数据库的最新历史记录,取得的提交会导入到没有名字的分支,这个分支可以从名为FETCH_HEAD的退出。
如:本地数据库和远程数据库的orign,如果在从B进行提交的状态下执行fetch,形成下面的历史记录
如果想要远程数据库的内容合并到本地数据库,可以进行合并FETCH_HEAD,或者重新执行pull
合并后,历史记录和pull相同,实际上pull的内容是fetch+merge组成的。
8.3 push
本地数据库oush到远程数据库时,要fast-forward合并push的分支。
如果发生冲突,push将会被拒绝,如果要进行共享本地数据库的分,需要明确的push,因此,没有执行push就不会给远程数据库带来影响,因此可以自由的创建自己的分支。
基本上,远程数据库共享的提交是不能修改的,如果进行修改的话,远程数据库同步的其他数据的历史就会变得很奇怪。
9 标签
标签是为了更加方便的参考提交而给它标上易懂的名称
Git使用2种标签:轻标签和注解标签,打上的标签是固定的,不能像分支那样可以移动位置
轻标签
添加名称
注解标签
添加名称
添加注解
添加签名
发布标签一般采用注解标签来添加注解或者签名的,轻标签是为了在本地暂时使用或一次性使用。
可以进行指定标签名称以退出
10 操作标签准备
10.1 事前预备
建立一个新目录,并在里面建立一个空的数据库。
这里建立一个tutorial的目录
mkdir tutorial
cd tutorial
git init
Initialized empty Git repository in
在tutorial目录创建一个名为myfile.txt 的档案,然后进行提交
git add myfile.txt
git commit -m "first commit"
[master (root-commit) a73ae49] first commit 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 myfile.txt
历史记录
10.2 添加轻标签
使用tag命令来添加标签 在<tagname>执行标签的名称
git tag <tagname>
在HEAD指向的提交里面 添加apple的标签,请执行以下命令
git tag apple
没有指定参数,显示标签的列表
git tag
apple
如果在log命令添加 --decorate选项执行,可以显示包含标签资料的历史记录。
git log --decorate
commit e7978c94d2104e3e0e6e4a5b4a8467b1d2a2ba19 (HEAD, tag: apple, master) Author: yourname <yourname@yourmail.com> Date: Wed Jul 18 16:43:27 2012 +0900 first commit
10.3添加注解标签
添加注解标签,可以在tag命令指定-a选项执行。
执行后会启动编辑区,请输入注解
也可以指定-m选项来添加注解。
git tag -a <tagname>
在HEAD指向的提交里添加名为banana的标签
git tag -am ”进行标签“ banana
如果在tag命令指定-n选项执行,可以显示标签的列表和注解
git tag -n
apple first commit
banana 进行标签
10.4删除标签
如果需要删除标签 ,在tag命令指定-d选项执行
git tag -d <tagname>
11.改写提交
11.1修改最近提交
指定amend选项执行提交,可以修改同一个分支最近的提交内容和注解
主要使用的场景:
添加最近提交时漏掉的档案。
修改最近提交的注解。
11.2 取消过去的提交
在revert取消指定的提交内容,也可以使用rebase -i,reset可以删除提交,但是不可以随便删除已经发布的提交,需要通过revert创建要否定的提交
使用场合:
安全的取消过去发布的提交
11.3 遗弃提交
在reset可以遗弃不再使用的提交,执行遗弃的时候,需要根据影响的范围而指定不同的模式,可以指定是否复原索引或工作树的内容。
默认:mixed模式,还有soft和hard模式。
如:
主要使用的场合:
1.复原修改过的索引的状态mixed
2.彻底取消最近的提交hard
3.只取消提交soft
11.4 提取提交
再check-pick 可以进行指定复制的提交,然后导入到现在的分支。
主要使用的场合
1.将弄错的分支的提交移动到正确的地方
2.把其他分支的提交添加到现在的分支
11.5 改写提交的历史记录
在rebase里面,我们可以进行改写,替换,删除,合并提交
主要使用场景
1.push之前,重新输入正确的提交注解。
2.清楚地汇合内容含义相同的提交。
3.添加最近提交时漏掉的档案
11.6 汇合分支上的提交,然后一同合并到分支
我们可以选择merge的选项 squash
使用这个进行指定分支进行合并,这样就可以把所有汇合的提交添加到分支上
主要使用的场景:
汇合主题分支的提交,然后合并提交到目的分支
12.改写提交
12.1commit --amend
进行修改最近的一次提交
进入stepup-tutorial/tutorial1目录。本地端的历史记录状态如
log命令进行确认历史记录
git log
commit 326fc9f70d022afdd31b0072dbbae003783d77ed Author: yourname <yourname@yourmail.com> Date: Mon Jul 16 23:17:56 2012 +0900 添加add的说明 commit 48eec1ddf73a7fb508ef664efd6b3d873631742f Author: yourname <yourname@yourmail.com> Date: Mon Jul 16 23:16:14 2012 +0900 first commit
首先打开sample.txt档案,并添加commit注释
add 把变更录入到索引里面
commit 记录索引的状态
git add sample.txt
git commit --amend
编辑工具会显示最近的一次提交信息,将消息进行修改为{添加add和commit的讲解}并进行保存。
进行log命令确认历史记录和提交信息。
git log
commit e9d75a02e62814541ee0410d9c1d1bf47ab1c057 Author: yourname <yourname@yourmail.com> Date: Mon Jul 16 23:17:56 2012 +0900 添加add和commit的讲解 commit 48eec1ddf73a7fb508ef664efd6b3d873631742f Author: yourname <yourname@yourmail.com> Date: Mon Jul 16 23:16:14 2012 +0900 first commit
12.2 revert
我们使用revert来取消{添加pull的讲解}提交
进入目标目录,显示历史记录
用log命令确认历史记录
git log
commit 0d4a808c26908cd5fe4b6294a00150342d1a58be Author: yourname <yourname@yourmail.com> Date: Mon Jul 16 23:19:26 2012 +0900 添加pull的讲解 commit 9a54fd4dd22dbe22dd966581bc78e83f16cee1d7 Author: yourname <yourname@yourmail.com> Date: Mon Jul 16 23:19:01 2012 +0900 添加commit的讲解 commit 326fc9f70d022afdd31b0072dbbae003783d77ed Author: yourname <yourname@yourmail.com> Date: Mon Jul 16 23:17:56 2012 +0900 添加add的讲解 commit 48eec1ddf73a7fb508ef664efd6b3d873631742f Author: yourname <yourname@yourmail.com> Date: Mon Jul 16 23:16:14 2012 +0900 first commit
打开sample.txt的档案,确认内容
add 把变更录入到索引里面
commit 记录索引的状态
pull 取得远端数据库的内容
类似:
add
:将更改添加到索引中 假设我们对"sample.txt"文件进行了修改,并希望将这些更改添加到Git的索引(暂存区)中。
git add sample.txt
commit
:记录索引的状态 在将更改添加到索引后,我们可以使用commit
命令将其记录为一个新的提交。同时,我们需要提供一个提交消息来描述所做的更改。
git commit -m "Update sample.txt file"
pull
:取得远程数据库的内容 如果我们与其他人协作开发,并且有一个远程Git存储库,我们可以使用pull
命令从远程数据库获取最新的内容,并将其合并到本地分支中。
git pull origin master
假设我们正在工作的分支是"master"分支,而远程Git存储库的名称是"origin"。通过运行以上命令,我们从"origin"远程数据库获取最新的内容,并将其合并到本地"master"分支中。
git revert HEAD
[master d47bb1d] Revert "添加pull的说明" 1 files changed, 1 insertions(+), 2 deletions(-)
打开sample.txt 档案进行查看,如果pull的说明消失了,就表明取消提交成功。
12.3 reset
使用reset来进行删除master分支最前面的两个提交。
进行目标目录,历史记录如下:
git log 确认信息
打开sample.txt的档案,确认内容
add 把变更录入到索引里面
commit 记录索引的状态
pull 取得远端数据库的内容
使用reset 进行删除提交
git reset --hard HEAD~~
HEAD is now at 326fc9f 添加add的说明
打开sample.txt进行查看 看看最近两个提交是否消失了
或者log命令确认历史记录
git log
进行还原
git reset --hard ORIG_HEAD
HEAD is now at 0d4a808 添加pull的说明
12.4 cherry -pick
进入目标目录,历史记录的状态如下:
git checkout master
git cherry-pick 99daed2
如果发生冲突就打开sample.txt,修改冲突的部分之后再提交
git add sample.txt
git commit
12.5 用rebase -i 汇合提交
进入目标目录,本地的历史记录
进行汇合(添加commit的讲解)和(添加pull的讲解)的修改,然后合并到一个提交。
如果汇合过去的提交
git rebase -i HEAD~
打开文本编辑器,看到HEAD到HEAD~~的提交如图
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. #
将第二行的pick改成squash,保存并退出,由于合并后要提交,所以接着会显示提交信息的编辑器,编辑信息后保存并退出。
这样两个提交就合并成一个提交
历史记录:
12.6 用rebase -i 修改提交
打开目标目录 历史记录如下
修改(添加commit的讲解)的内容
使用rebase -i ,进行选择要进行修改的提交
git rebase -i HEAD~~
打开文本编辑器,看到HEAD到HEAD~~的提交如:
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. #
将第一行的pick改成edit 保存后退出
显示:
Stopped at d286baa... 添加commit的说明 You can amend the commit now, with git commit --amend Once you are satisfied with your changes, run git rebase --continue
打开sample.txt 适当进行修改commit的讲解部分
add 把变更录入到索引中 commit 记录索引的状态 pull 取得远端数据库的内容
用commit --amend保存修改
$ git add sample.txt $ git commit --amend
通知这个提交的操作已经结束,指定 --continue选项执行rebase $ git rebase --continue
这时,有可能其他提交会发生冲突, 请修改冲突部分后再执行add和rebase --continue。这时不需要提交。如果在中途要停止rebase操作,请在rebase指定--abort选项执行,这样就可以抹去并停止在rebase的操作。
提交的修改完成了。如果要把多个提交修改成edit,下一个要修改的提交会退出,请执行同样的修改。
实际上,在rebase之前的提交会以ORIG_HEAD之名存留。如果rebase之后无法复原到原先的状态,可以用git reset --hard ORIG_HEAD复原到rebase之前的状态。
12.7 merge --squash
打开目标目录 ,历史记录
将所有分支合并成一个进行提交,并导入到master分支
切换到master分支 指定--squash选项执行merge
git checkout master
Switched to branch 'master'
git merge --squash issue1
将issue1合到master
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.
发生了冲突
打开sample.txt ,进行修改冲突的部分,然后进行提交
git add sample.txt
git commit
[master 0d744a7] Conflicts: sample.txt 1 files changed, 4 insertions(+), 0 deletions(-)
issue1分支上所有的提交都汇合并添加到master分支了。可用log命令确认历史记录。