老夫的毕生功力都在这了…

通常我们工作时是这样操作

说一下使用 git 做版本控制的时候的工作流程

1
2
3
4
git add -A           #需要添加到版本库中的文件 -A 就代表着所有文件(除开了 .gitignore忽略掉的文件)
git commit -m '本次提交的备注'
git pull            #将远程的库和本地的库版本同步一下,因为远程库可能发生了修改(多人合作开发时)
git push          

这样操作的前提是本地远程都是同一个 master 分支上

最可能会碰到的问题

以上操作前两步通常不会碰到问题,最容易发生问题的是 git pull 这一步 因为多人开发时难免碰到同时修改了同一个文件,那么就会产生冲突 git 是根据文件每行发生的修改进行的判定的,如果同时对同一文件的同一行发生了修改,就卡死到这一步上了

怎么解决这个问题

我常用的是命令行和 phpstrom 中的版本控制工具,最推荐的是命令行操作,别的图形界面也是调的命令行接口 直接学会git 的命令是学习成本最低的一种方式,一次学会到处可用啊!

命令行还有个强大的地方就是它的提示通常就是你解决问题的方法,照着提示打就行(要善用提示啊,别看见报错就慌了)

我们做一个实验,我自己的一个版本库本地和远程同时发生了修改,而且是操作的同一个文件, 我直接进行 git push操作 看到提示没?提示中的 hint 中说了,向远程库中更新被拒,因为远程有了修改而本地没有(说白了就是没同步), 这通常发生在另一个版本库向远程推送了相同的文件(就是两个人在这个版本下同时操作了同一个文件), 提示中给出原因之后紧接着给出了解决办法(e.g., 'git pull ...')before pushing again,

我们按着它给的提示操作一下 通常如果两个人之间的操作不发生冲突比如同时修改了同一个文件的同一行的情况下就会进入commit的 编辑界面了,但是我给他人为的造成一个错误,这个错误就是我们最常碰到的错误,合并冲突 看到提示中的最后一行了没有? Automatic merge failed; fix conflicts and then commit the result. 自动合并失败了,请修复冲突并再次提交

如果文件很多我怎么去找到它?

  • 一种是靠界面工具主动把错误推到你面前
  • 另一种就是自己去找了

第一种方法坑爹的地方就是好多工具他给你提示就提示一次,你如果给关了就不会再提示了,但是该提交不上去的 还是提交不上去,而且如果是线上火速修复的时候你的编辑器是帮不到那么远的 我们选第二种,肯定不是挨个文件去翻啊!会死人的

有一个很有用的命令

1
git status

标红的文件都给你了,而且还给你了需要执行的命令,你别假装看不到啊! 当然这个时候直接git add && git commit会出事的,你还没解决冲突呢! 我们去这个冲突文件中解决掉冲突本地能跑通了再提交,而且这个错误提示会指名文件路径的,我这个冲突文件 因为正好是在项目的根目录下才没有的

打开这个文件我们看到如下的内容: 我这是在 phpstrom 中打开的文件,如果phpstrom 能读取到你项目中的 .git/ 目录是可以进行版本控制的 这里phpstrom 就帮你把冲突文件标红了,多么醒目~当然这也是我们自己找的 如果文件内容特别多但是就一两处冲突时我们直接搜索关键词 HEAD或者<<<<<<<就行,你懂的… 被尖角号扩起来的就是冲突的地方,接下来就是保孩子还是保大人解决冲突的时候了,找到谁和你改的同一处代码

什么?你说你找不到是谁?你没看到代码冲突块下的 779833d952d8a6557b2e8eba3bd192ede5cb6ca0 这一段文字吗?你先别激动,这个点还不适合开车,这个是提交的 commit-id,你每次提交都会产生的一个标识 要查看这到底是谁和我的代码冲突了就执行下面的命令

1
git log 779833d952d8a6557b2e8eba3bd192ede5cb6ca0

第一行就是你要的结果, 如果直接git log -p 就是列出所有的提交记录 -p 就是显示出修改的地方

冲突块部分 HEAD就是你写的代码,下面的是别人写的,去掉其中一个把那些标签清理干净,测试一下没问题了 再git add && git commit && git pull && git push 这四连技好了,世界清净了

这合并的时候发生了什么?

这是我在 segmentfault 中给出的答案:

比如你从一个git log为1,2,3,4,5,6的远程库拉取到了本地, 另一个同事也拉取了同样的代码,而且你的同事先于你提交到远程了, 此时远程的版本是1,2,3,4,5,6,7_new,8_new, 而你当前只是本地的版本1,2,3,4,5,6,7_local,8_local,9_local 从这里你就能看出你前一部分和远程的一样,后一部分和远程的不一样, 这个时候你不能正常推送上去的,如果你采取git push origin master --force 那么远程的版本就变成了1,2,3,4,5,6,7_local,8_local,9_local 之前你同事推送的7_new,8_new这两次推送被覆盖了,这不是大家想要的情况 因此需要git pull来将本地的版本合并成样 1,2,3,4,5,6,7_new,7_local,8_local,8_new,9_local,10_commit_merge 远程和本地的排序是按当时 commit 的时间来排的,最后一个10_commit_merge就是你本地远程合并的标志,最后你推送到远程仓库的应该也是这个, 因为你们操作的是同一个库始终要保持代码的同步,所以一旦版本库发生改动同一分支下的所有人都要跟着去同步他,因为各开发各的直接往上推 git 还没智能到帮你处理冲突的地步 答案链接

如果只想合并分支里的几个文件怎么办?

比如我有两个分支

1
2
* alpha
  dev

我只要 dev 中的某几个文件, 比如 README.md 和 LICENSE.md, 那么我就

1
git checkout dev /path/to/README.md /path/to/LICENSE.md

就会拉取 dev 分支中的这几个文件覆盖到 alpha 分支上, 注意拉取的文件会强制覆盖, 然后你 git diff 一下这几个文件看有没有问题, 直接git commit && git pull && git push 一套带走就行