前言
分布式 VCS 和中央式的区别在于,分布式 VCS 除了中央仓库之外,还有本地仓库:团队中每一个成员的机器上都有一份本地仓库,这个仓库里包含了所有的版本历史,或者换句话说,每个人在自己的机器上就可以提交代码、查看历史,而无需联网和中央仓库交互。
优点:
- 大多数的操作可以在本地进行,所以速度更快,而且由于无需联网,所以即使不在公司甚至没有在联网,你也可以提交代码、查看历史,从而极大地减小了开发者的网络条件和物理位置的限制。
- 由于可以提交到本地,所以你可以分步提交代码,把代码提交做得更细,而不是一个提交包含很多代码,难以 review 也难以回溯。
缺点:
- 由于每一个机器都有完整的本地仓库,所以初次获取项目的时候会比较耗时。
- 由于每个机器都有完整的本地仓库,所以本地占用的存储比中央式 VCS 要高。
实用指南
- 把远程仓库取到本地
1 | git clone 远程仓库地址 |
- 把写完的代码提交
1 | 添加文件到暂存区 |
git log
列出提交历史git log -p
查看详细历史git log --stat
查看简要统计git show
查看具体的 commitgit diff --staged
比对暂存区和上一条提交git diff
比对工作目录和暂存区git diff HEAD
比对工作目录和上一条提交
- .gitignore——排除不想被管理的文件和目录
1 | .gitignore,这个文本文件记录了所有你希望被 Git 忽略的目录和文件。 |
- 偏移符号
1 | 在 Git 中,有两个「偏移符号」: ^ 和 ~。 |
HEAD、master 与 branch
1.HEAD 2.master 3.branch -------------------------------------------------------------------- 1.HEAD 是指向当前 commit 的引用,它具有唯一性,每个仓库中只有一个 HEAD。在每次提交时它都会自动向前移动到最新的 commit 2.branch 是一类引用。HEAD 除了直接指向 commit,也可以通过指向某个 branch 来间接指向 commit。当 HEAD 指向一个 branch 时,commit 发生时,HEAD 会带着它所指向的 branch 一起移动。 3.master 是 Git 中的默认 branch,它和其它 branch 的区别在于: a.新建的仓库中的第一个 commit 会被 master 自动指向; b.在 git clone 时,会自动 checkout 出 master。 4.branch 的创建、切换、删除和提交: a.创建 branch 的方式是 git branch 名称 或 git checkout -b 名称(创建后自动切换); b.切换的方式是 git checkout 名称; c.push 的时候,如果当前分支是一个本地创建的分支,需要指定远程仓库名和分支名,用 git push origin branch_name 的格式,而不能只用 git push; 或者可以通过 git config 修改 push.default 来改变 push 时的行为逻辑。 d.git branch -a 看到所有分支 5.branch 的删除: a.git branch -d 名称。 b.git push origin -d branch_name # 用 -d 参数把远程仓库的 branch 也删了 c.git push origin :branch 注意: 1. HEAD 指向的 branch 不能删除。如果要删除 HEAD 指向的 branch,需要先用 checkout 把 HEAD 指向其他地方。 2. 由于 Git 中的 branch 只是一个引用,所以删除 branch 的操作也只会删掉这个引用,并不会删除任何的 commit(一定时间后,会被 Git 的回收机制删除掉) 3. 出于安全考虑,没有被合并到 master 过的 branch 在删除时会失败(如果你确认是要删除这个 branch,可以把 -d 改成 -D)
Merge
从两个 commit「分叉」的位置起,把目标 commit 的内容应用到当前 commit(HEAD 所指向的 commit),并生成一个新的 commit;
适用场景
合并分支
1
21. 当一个 branch 的开发已经完成,需要把内容合并回去时,用 merge 来进行合并。
2. git merge branch1pull 的内部操作
1
1. pull 的实际操作其实是把远端仓库的内容用 fetch 取下来之后,用 merge 来合并。
冲突
- 解决冲突后手动 commit
- git merge –abort 【放弃解决冲突,取消 merge】
Feature Branching:工作流
- 任何新的功能(feature)或 bug 修复全都新建一个 branch 来写;
- branch 写完后,合并到 master,然后删掉这个 branch。
Git合并特定commits 到另一个分支
- 合并某个分支上的单个commit
1 | 1. git log 查看想选择哪些commits进行合并 |
- 合并某个分支上的一系列commits
1 | 假设需要合并feature分支的commit dd2e86 ~a6fd86 到master分支。 |
rebase——在新位置重新提交
git rebase
目标基础点
场景: 我在主分支commit a时新建了新分支,此时开始分叉,分叉后我又在主分支改了东西commit b,此时我后悔了,我不该在commit a时分叉的。 因为commit b的东西我新分支也需要,此时用衍合(rebase)。 就等于我丢弃原分叉,在commit b重新分叉(原分叉的改动内容当然也是带上的,没有丢) 注意:为了避免和远端仓库发生冲突,一般不要从 master 向其他 branch 执行 rebase 操作。 而如果是 master 以外的 branch 之间的 rebase(比如 branch1 和 branch2 之间),就不必这么多费一步,直接 rebase 就好。
其它特性
git commit --amend 对最新一条 commit 进行修正,生成一条新的commit替换了原commit。 注意:commit之后,push之前使用有效;只针对目前最新的 commit 有效 git reset --hard 目标commit 撤销最新的提交 撤销过往的提交 1. 用 git rebase -i 在编辑界面中删除想撤销的 commits 2. 用 git rebase --onto 在 rebase 命令中直接剔除想撤销的 commits git push origin branch1 -f 忽略冲突,强制 push git revert HEAD^ commit 撤销提交 reset 的三种参数: 1. --hard:重置位置的同时,清空工作目录的所有改动; 2. --soft:重置位置的同时,保留工作目录和暂存区的内容,并把重置 HEAD 的位置所导致的新的文件差异放进暂存区。 3. --mixed(默认):重置位置的同时,保留工作目录的内容,并清空暂存区。 场景: 当你手头有一件临时工作要做,需要把工作目录暂时清理干净,那么你可以: git stash -u (扔) git stash pop (取) 恢复已删除的 branch 1. git reflog 查看一下 HEAD 的移动历史 2. git checkout c08de9a 3. git checkout -b branch1 注意:不再被引用直接或间接指向的 commits 会在一定时间后被 Git 回收 tag:不可移动的 branch,tag 被用来在关键版本处打标记用。 git config: Git 的设置 https://git-scm.com/docs/git-config cherry-pick:把选中的 commits 一个个合并进来
参考: