git pull报错以及git stash
为了方便我写博客做知识管理,我的台式机(主力机)和Windows平板上都有一份laurenfrost.github.io的repo。但我更多的时间是坐在台式机前,所以大部分的更新都是从我台式机上的repo来push到GitHub的。至于我的平板,则只有偶尔出门的时候会用,因此平板上的repo的进度就落后很多。而且经常有只在平板上写了几个字就放在那里了,最后是在台式机上重新hexo new了一个post,然后deploy的。
unrelated histories
今天我为了乘凉跑到咖啡店里,打算接着写之前的内容的的,就打算直接把GitHub里的更新给pull到平板里的repo。结果就遇到了下面的报错:
1 |
|
unrelated?我他妈直接问号。怎么就让它unrelated了呢?果断Google。然后我在这里找到了解决方案。
fatal: refusing to merge unrelated histories
这个报错指的是git正在尝试把两个不相关的project给merge到一起(或者说,有两个project,它们之间没有意识到另一方的存在,它们各自都有自己的commit),这样一来git就无从判断究竟该舍弃哪些文件、更新哪些文件,只能报错。
造成这种情况一般有两种可能:
- 你之前克隆了这个repo,但是
./.git
文件夹里面的信息现在损坏了。这就使得git无法确定你本地repo的历史和你的意图,当你push或者pull远程repo的时候就会报这个错。- 还有一种情况,你在你的repo上添了几个commit,然后你pull远程repo。但这个时候远程repo已经有别的commit的了,现在git拿不准要不要删了你本地的commit,就只能报错了。
解决办法很简单,在命令后面加一个--allow-unrelated-historie
的参数即可,比如:
1git pull origin master --allow-unrelated-histories
看到这个命令我突然意识到我犯了一个傻逼的错误:我没有指定要pull的branch。
1 |
|
如果不指定branch的话,命令默认pull的branch是master。而根据GitHub的规则,master必须放编译好的html页面及其资源,所以我把自己hexo博客的source以及theme里的相关配置文件全部放在了一个叫hexo的branch里。因此这个平板的repo里全是hexo branch里的文件。checkou一下果然如此:
1 |
|
那么在命令里加上hexo不就解决了吗?
Naive!又报错了!
1 |
|
本地repo跟远程repo相比还是有change,还提示我要么先commit,要么就stash它们。
git stash
stash是啥?是没见过的浮莲子啊。
stash 英 [stæʃ] 美 [stæʃ]
v. 存放;贮藏;隐藏;
n. 贮藏物;
根据这个博客所说,stash可以把当前工作现场“保存”起来,等以后恢复现场后继续工作。
假设有两个分支,master和subWork,当前分支是subWork。
当前分支subWork上的工作尚未完成,如果有另一项任务需要优先完成,或者出现BUG需要立刻修复。此时需要另外创建一个分支来工作,可以把当前工作现场“保存”起来,等以后恢复现场后继续工作。
一开始的状态是这样的:
1
2
3
4
5
6$ git status
On branch subWork
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: test.txt这个时候我们用stash来保存工作现场:
1$ git stash
然后我们再查看状态,工作区就是干净的:
1
2
3$ git status
On branch subWork
nothing to commit (working directory clean)接下来我们就能进行正常的工作了。
等工作完成之后,一开始的工作现场还能恢复:
1$ git stash pop
git stash
可以多次使用,然后用git stash list
来查看所有保存的工作现场,然后用git stash apply
来恢复。
使用git stash apply
恢复之后,被恢复的现场不会自动删除,需要手动使用git stash drop
来手动删除。
其他方案
而且对于这种报错,其实除了stash之外还有别的思路存在:为什么不问问神奇的stackoverflow呢?
这个页面里大佬们提供了好几个方法。
stash
首先是前面说的stash:
1 |
|
--include-untracked
这个参数可以连git没有track的文件也一起保存。
直接overwrite
可以干脆不要本地的修改了,直接让远程的repo内容覆盖这些修改:
1 |
|
reset
更干脆的,直接放弃到上次push之前的修改,全盘接受远程repo:
1 |
|
感想
git的使用像写命令行脚本一样,非常灵活,可以说条条大路通罗马,关键在于理解它的工作原理。一旦吃透了它的工作机制,解决这些小问题便是易如反掌了。
关键还是要多熟悉熟悉它们。