2018年学习计划(git篇)

直接快照,而非比较差异

Git只关心文件数据的整体是否发生变化,而大多数其他系统则只关心文件内容的具体差异。Git更像是一个小型的文件系统,它保存每次更新时的文件快照。所以Git近乎所有的操作都可以在本地执行。

三种状态

  • 已提交(committed):该文件已经被安全地保存在本地数据库中了
  • 已修改(modified):修改了某个文件,但还没有提交保存
  • 已暂存(staged):把已修改的文件放在下次提交时要保存的清单中

分支

  • 创建分支

git checkout -b newBranch相当于:

1
2
git branch newBranch
git checkout newBranch
  • 删除分支
1
git branch -d newBranch
  • 基本合并
1
2
git checkout master
git merge newBranch
  • 冲突的合并

任何包含未解决冲突的文件都会以未合并(unmerged)状态列出。可以手动或通过图形工具来解决冲突:

1
git mergetool

冲突解决之后再add提交。

1
2
3
git branch // 查看所有分支
git branch -v // 查看所有分支最后一次commit的信息
git branch --merged/--no-merged // 查看已合并/未合并分支

分支式的工作流程

长期分支

master分支中保留完整稳定的代码,develop或next分支专门用于后续的开发,仅用于稳定性测试,当然并不是说一定要绝对稳定,不过一旦进入某种稳定的状态,便可以把它合并到master里。

特性分支

一个特性分支是指一个短期的,用来实现单一特性或与其相关工作的分支

远程分支

当我们从远程仓库克隆时,git会自动将你仓库命名为origin,并下载其中所有数据,建立一个指向它的master分支,在本地命名为origin/master,你无法在本地更改其数据。

接着,git建立一个本地属于你的master分支,始于origin上master分支相同的位置。只要你不和服务器通讯,你的origin/master分支不会移动。

可以通过git fetch origin命令来进行同步。

推送

如果你有个叫 serverfix 的分支需要和他人一起开发,可以运行 git push (远程仓库名) (分支名) :

1
git push origin serverfix

Git 自动把 serverfix 分支名扩展为 refs/heads/serverfix:refs/heads/serverfix ,意为“取出我的 serverfix 本地分支,推送它来更新远程仓库的 serverfix 分支”

也可以运行 git push origin serverfix:serferfix 来实现相同的效果,它的意思是“提取我的 serverfix 并更新到远程仓库的 serverfix”

值得注意的是,在 fetch 操作抓来新的远程分支之后,你仍然无法在本地编辑该远程仓库。换句话说,在本例中,你不会有一个新的 serverfix 分支,有的只是一个你无法移动的 origin/serverfix 指针。

如果要把该内容合并到当前分支,可以运行 git merge origin/serverfix 。如果想要一份自己的 serverfix 来开发,可以在远程分支的基础上分化出一个新的分支来:

1
git checkout -b serverfix origin/serverfix

跟踪分支

从远程分支检出的本地分支,称为跟踪分支(tracking branch)。跟踪分支是一种和远程分支有直接联系的本地分支。在跟踪分支里输入 git push ,Git 会自行推断应该向哪个服务器的哪个分支推送数据。反过来,在这些分支里运行 git pull 会获取所有远程索引,并把它们的数据都合并到本地分支中来。

在克隆仓库时,Git 通常会自动创建一个 master 分支来跟踪 origin/master 。这正是 git push 和 git pull 一开始就能正常工作的原因。当然,你可以随心所欲地设定为其它跟踪分支,比如 origin 上除了 master 之外的其它分支。刚才我们已经看到了这样的一个例子: git checkout -b [分支名] [远程名]/[分支名] 。如果你有 1.6.2 以上版本的 Git,还可以用 –track 选项简化:

1
2
3
$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch refs/remotes/origin/serverfix.
Switched to a new branch "serverfix"

要为本地分支设定不同于远程分支的名字,只需在前个版本的命令里换个名字:

1
2
3
$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch refs/remotes/origin/serverfix.
Switched to a new branch "sf"

删除远程分支

1
2
3
$ git push origin :serverfix
To git@github.com:schacon/simplegit.git
- [deleted] serverfix

衍合

把一个分支整合到另一个分支的办法有两种: merge(合并) 和 rebase(衍合)

衍合基础

rebase命令可以把在一个分支里提交的改变在另一个分支里重放一遍:

1
2
git checkout experiment
git rebase master

你可以经常使用衍合,确保在远程分支里的提交历史更清晰。比方说,某些项目自己不是维护者,但想帮点忙,就应该尽可能使用衍合:先在一个分支里进行开发,当准备向主项目提交补丁的时候,再把它衍合到origin/master 里面。这样,维护者就不需要做任何整合工作,只需根据你提供的仓库地址作一次快进,或者采纳你提交的补丁。

更多有趣的衍合

1
$ git rebase --onto master server client

检出 client 分支,找出 client 分支和 server 分支的共同祖先之后的变化,然后把它们在 master 上重演一遍

git rebase [主分支][特性分支]命令会先检出特性分支 server ,然后在主分支 master 上重演:

1
git rebase master server

衍合的风险

永远不要衍合那些已经推送到公共仓库的更新

如果把衍合当成一种在推送之前清理提交历史的手段,而且仅仅衍合那些永远不会公开的 commit,那就不会有任何问题。如果衍合那些已经公开的 commit,而与此同时其他人已经用这些 commit 进行了后续的开发工作,那你有得麻烦了。