Git - 变基 (git-scm.com)

GitLearn

git

基本流程

  1. 使用git命令将远程仓库上的文件克隆到本地仓库中

  2. 从本地仓库中检出文件到工作区(一般都自动完成)

  3. 将新创建的文件添加到暂存区

  4. 将暂存区中的内容提交到本地仓库

  5. 将本地仓库中的内容推送到远程仓库上

Git-远程分支,远程跟踪分支,跟踪分支的区别

远程分支

远程分支对应的英文为remote branch,其就是在远程仓库的普通分支,比如远程仓库上的master,自己在远程仓库创建的分支,以及自己推送到远程仓库上去的在远程仓库上的分支。当运行git push (仓库名) 分支名 的命令时,便会在远程仓库创建远程分支。

远程跟踪分支

远程跟踪分支对应的英文名称为remote-tracking branch,虽然仅仅多了tracking这个词,但是其作用与性质却与远程分支有很大的不同,远程跟踪分支是本地仓库对远程仓库中的某个远程分支的状态的记录,它们以 “(远程仓库名)/(分支名)” 形式命名。 例如,如果你想要看你最后一次与远程仓库 origin 通信时master 分支的状态,你可以查看 origin/master 分支。远程跟踪分支的作用是告诉用户其所跟踪的远程分支的状态(即指向哪一个commit),因而它在本地是只读的,用户是无法自行修改它的指向。其指向将在用户与远程仓库通信时自动改变,这里的通信是指执行诸如git fetch等从远程仓库获取数据的操作

跟踪分支

跟踪分支的英文名称为tracking branch,从一个远程跟踪分支产生出的一个本地分支便是跟踪分支,该本地分支对应的远程跟踪分支称为上游分支。跟踪分支是与远程分支有直接关系的本地分支,当克隆一个仓库时,它通常会自动地创建一个跟踪 origin/mastermaster 分支。创建跟踪分支可以使用git checkout -b [branch] [remotename]/[branch],还可以使用–track快捷方式

1
2
3
4
5
6
$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

更多创建方式可参见git pro 3.5节。

  • 那么跟踪分支有什么作用呢?

    跟踪分支为本地分支和远程分支之间建立了一种联系,方便了远程分支和本地分支的同步。 如果在一个跟踪分支上输入 git pull,Git 能自动地识别去哪个服务器上抓取、合并到哪个分支。同时,跟踪分支还能查看本地分支与对应的远程分支之间的超前落后情况,如使用git branch -vv语句

1
2
3
4
5
$ git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets
master 1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
testing 5ea463a trying something new

这里可以看到 iss53 分支正在跟踪 origin/iss53 并且 “ahead” 是 2,意味着本地有两个提交还没有推送到服务器上。 也能看到 master 分支正在跟踪 origin/master 分支并且是最新的。 接下来可以看到 serverfix 分支正在跟踪 teamone 服务器上的 server-fix-good 分支并且领先 3 落后 1,意味着服务器上有一次提交还没有合并入同时本地有三次提交还没有推送。 最后看到 testing 分支并没有跟踪任何远程分支。

小结

远程分支就是在远程仓库上的普通分支。远程跟踪分支是在本地的只读的记录远程分支状态的分支,其指向用户无法移动,当使用git fetch等指令时其指向会依照远程仓库自动移动。跟踪分支是从远程跟踪分支上生成的本地分支,跟踪分支提供了本地分支与远程分支更紧密的联系,可以看出本地分支与对应的远程分支的超前落后情况,也可以使用git pull 指令轻松的将远程分支拉取到对应的跟踪分支。

  1. dev分支合并到master分支

1
2
3
4
5
6
7
8
9
10
11
// 切到master
git checkout master

# dev分支的代码合并到master分支 ; 把参数分支((dev)合并到当前分支;并且移动当前分支到最新处
git merge dev

// 查看状态
git status

// 提交远程
git push origin master

rebase 和merge

Git - 变基 (git-scm.com)

在 Git 中整合来自不同分支的修改主要有两种方法:merge 以及 rebase

  1. merge方法是会生成一个新的快照

  2. rebase

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    git checkout experiment
    ## 把当前分支上的新的修改都 移动到 参数分支(master)上,(该分支和参数分支最近公告祖先之间的修改都不要了,直接重新提交到参数分支之后); 并且移动当前分支指针到最新处,而参数分支(master)的指针,需要再checkout和merge 当前分支,最终两个指针在同一个位置
    git rebase master
    First, rewinding head to replay your work on top of it...
    Applying: added staged command
    它的原理是
    首先找到这两个分支(即当前分支 experiment、变基操作的目标基底分支 master) 的最近共同祖先 C2,
    然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件,
    然后将当前分支指向目标基底 C3,
    最后以此将之前另存为临时文件的修改依序应用。 (译注:写明了 commit id,以便理解,下同)

    如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。

    变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。 如果你已经将提交推送至某个仓库,而其他人也已经从该仓库拉取提交并进行了后续工作,此时,如果你用 git rebase 命令重新整理了提交并再次推送,你的同伴因此将不得不再次将他们手头的工作与你的提交进行整合,如果接下来你还要拉取并整合他们修改过的提交,事情就会变得一团糟。

变基 vs. 合并

至此,你已在实战中学习了变基和合并的用法,你一定会想问,到底哪种方式更好。 在回答这个问题之前,让我们退后一步,想讨论一下提交历史到底意味着什么。

有一种观点认为,仓库的提交历史即是 记录实际发生过什么。 它是针对历史的文档,本身就有价值,不能乱改。 从这个角度看来,改变提交历史是一种亵渎,你使用 谎言 掩盖了实际发生过的事情。 如果由合并产生的提交历史是一团糟怎么办? 既然事实就是如此,那么这些痕迹就应该被保留下来,让后人能够查阅。

另一种观点则正好相反,他们认为提交历史是 项目过程中发生的事。 没人会出版一本书的第一版草稿,软件维护手册也是需要反复修订才能方便使用。 持这一观点的人会使用 rebasefilter-branch 等工具来编写故事,怎么方便后来的读者就怎么写。

现在,让我们回到之前的问题上来,到底合并还是变基好?希望你能明白,这并没有一个简单的答案。 Git 是一个非常强大的工具,它允许你对提交历史做许多事情,但每个团队、每个项目对此的需求并不相同。 既然你已经分别学习了两者的用法,相信你能够根据实际情况作出明智的选择。

总的原则是,
==只对尚未推送或分享给别人的本地修改执行变基操作清理历史, 从不对已推送至别处的提交执行变基操作==,这样,你才能享受到两种方式带来的便利。

branch, tag

tag就是一个只读的branch,一般为每一个可发布的里程碑版本打一个tag

tag就像是一个里程碑一个标志一个点,branch是一个新的征程一条线;

tag是静态的,branch要向前走;

稳定版本备份用tag,新功能多人开发用branch(开发完成后merge到master)

git查看各个branch之间的关系图

  1. 使用git log命令
1
git log --graph --decorate --oneline --simplify-by-decoration --all

说明:

–decorate 标记会让git log显示每个commit的引用(如:分支、tag等)

–oneline 一行显示

–simplify-by-decoration 只显示被branch或tag引用的commit

–all 表示显示所有的branch,这里也可以选择,比如我指向显示分支ABC的关系,则将–all替换为branchA branchB branchC

  1. 使用gitk工具
1
gitk --simplify-by-decoration --all

reference

  1. Git-远程分支,远程跟踪分支,跟踪分支的区别_set as tracked branch-CSDN博客
  2. git 分支合并(dev合并到master分支)_git dev合并到master-CSDN博客
  3. git常用命令及命令流程_git常用的命令有哪些(5分)?说一下你在开发过程中合并代码流程(5分)_明子~的博客-CSDN博客
  4. git merge和git rebase的区别, 切记:永远用rebase - 知乎 (zhihu.com)
  5. 浅谈github git命令 branch tag - 知乎 (zhihu.com)
  6. Git - 变基 (git-scm.com)
  7. https://stackoverflow.com/questions/5298972/relationship-between-n-git-branches