git 多人协同模式
最佳实践建议
- 尽可能的在自己的本地分支上开发新功能.
- 功能开发分支,是可供运行与测试的hot code分支,请确保每个提交测试分支的功能可运行,可测试,并且包含了最新的master分支功能.
- master分支为稳定主线分支,以在master分支打tag的静态版本来上线或回滚.
- 专人负责将功能开发分支merge到master,code review,打tag和上线.
- 千万不要使用git add *,git add .,git commit -a,除非你知道自己在做什么
- 尽量使用git commit -i,git commit,并唤起默认编辑器,可以有效防止误提交
- 分支合并时尽量使用git merge --no-ff origin/branch-name,尤其是将功能分支代码合并进master分支时,目的是人为制造分叉点,清晰描述合并过程
git 多分支合并最佳实践
以 work-branch 为例,约定此分支为从最新的 master 分支创建的功能开发分支.
1. 创建功能开发分支
$ git checkout master # 切到 master 分支
$ git pull origin master # 拉取最新 master 分支代码,因为可能有新功能已经合并上线
$ git checkout -b work-branch # 创建并切换新的分支
2. 在功能开发分支开发新功能,建议频繁按小功能完成点提交代码,完成自测
3. 将 master 最新功能合并进功能开发分支,并推送到远端
$ git fetch --all # 抓取所有远端分支的最新代码
$ git merge --no-ff origin/master # 将远端 master 最新代码合并进入功能开发分支
如果有冲突,用 `git log -p 冲突文件` 查看改动作者,尽量和原作者共同裁决冲突.
$ git push origin work-branch # 将功能开发分支推送到远端
4. 将新功能分支 work-branch 合并到 master
$ git fetch --all # 抓取所有远端分支的最新代码
# 以下操作为容错操作,建议所有合并代码的同学按此指导操作,因为很多功能开分的同学会忘记合并 master 分支上的最新代码
$ git checkout work-branch # 切到待合并分支
$ git pull origin work-branch # 拉取功能分支最新代码并在本地完成自动合并
$ git fetch --all # 抓取所有远端分支的最新代码
$ git merge --no-ff origin/master # 将远端 master 最新代码合并进入功能开发分支
$ git push origin work-branch # 将变化推送到远端
# 正式开始合并操作
$ git checkout master # 切换分支
$ git pull origin master # 拉取并在本地合并 master 分支最新代码
$ git fetch --all # 抓取所有远端分支的最新代码,或者使用 git fetch -p,在抓取远端分支的同时,会清除远端已经删除而本地有记录的分支
$ git merge --no-ff origin/work-branch # 将功能分支的远端 origin/work-branch 合并进 master 本地分支
如果有冲突,用 `git log -p 冲突文件` 查看改动作者,尽量和原作者共同裁决冲突.
$ git push origin master # 将合并结果推送到远端,完成合并
5. (可选)打 tag 上线,删除已合并的本地分支和远端分支
$ git tag -a v1.0.0 -m 'release-v1.0.0' # 打 tag,请具体对待
$ git push --tags # 推送 tags 到远端
$ git branch -d work-branch # 删除本地已经合并的功能开发分支
$ git push origin :work-branch # 删除远端已合并的分支
git 交叉合并后出现的灵异现象
所谓的交叉合并类似场景为,从 master 上创建分支 dev和test,在 test 分支开发新功能,他人的新功能被合并到 dev 分支;这时将 dev 合并进 test,然后将 test 合并至 dev;之后将 test 合到 master 上线,完成上线后又将 master 合至 dev.
这样操作后出现的诡异现现象目前遇到两种:
1. 递归合并.合并两个分支时,没有任何文件需要合并,仅提示进行了递归合并. git diff 两个无端分支时没有差异,但人工查看代码时发现,有分支代码并没有合并进去.
提示语如下:
Already up-to-date!
Merge made by the 'recursive' strategy.
2. 每次合并都会出现几个与本分支功能无关的代码冲突,反复解决,反复冲突.
建议: 合并代码时一定要搞清楚合并方向,完成合并后在 push 之前,做好必要的 code review,利人利己.
修复冲突
$ git apply PATCH --reject
$ edit edit edit
$ git add FIXED_FILES
$ git am --resolved
放弃更新
$ git am --abort
直接刪除 rebase-apply
$rm -rf .git/rebase-apply
git rebase 后本地commit记录丢失
解决方法
1. cd .git/logs/refs/heads,找到对应的分支
2. 打开对应的文件,找到对应的日志(这个时候,认真写提交日志的好处就体现出来了)
3. 简单粗爆法:git reset --hard HASH
忽略合并日志
$ git log --no-merges --first-parent
$ git log --no-merges ^other-branch-1 ^other-branch-2 ^other-branch-3
rebase 还是 merge?
rebase和merge是代码观察者查看代码线性变化的不同维度,对最终合并的代码来讲,没有任何区别.merge是完全的以时间为线性轴,体现出源码在不同时间点上发生的变化;而rebase是提交源码作者为轴,将同一作者的提交在目标源码的最后基线上线性的合并,表现为分支功能的代码提交是线性的,而不是与协作者提交相穿插.
建议同分支合并使用rebase,跨分支合并使用merge,这样不会丢失关键的merge message.
git使用https方式记住密码
git使用https方式进行连接时,默认每次推送时都要输入用户名和密码。
git config credential.helper store
为当前仓库设置记住密码,设置后,只要在推送一次,以后就不需要用户名和密码了
查看某次合并操作中的代码改动
- 找到合并操作对应的log
$ git log
- 有合并操作的地方,会产生形如以下的日志:
commit 1a079789427f9aa7b47f7dc699355947cc9e83ff
Merge: 0e9fa5d e5521e2
…
- 通过版本号区间的方式查看合并操作中代码的改动
$ git diff 0e9fa5d e5521e2
从git提交历史中「恢复」文件修改时间
git ls-files | while read file; do touch -d ( g i t l o g − 1 − − f o r m a t = " @ (git log -1 --format="@%ct" " (gitlog−1−−format="@file") “$file”; done