问题描述
初始情况是, a和b的代码库是完全相同的.
1, a修改了代码.然后成功push到 bitbucket2, a做了更改是: 程序中的目录app/storage/sessions/刚开始没有加入到.gitignore中,所以a在.gitignore中加了这个目录.其它的是一些程序的代码.3, b本身有代码,但没有修改.因为a更新了,所以b进行pull操作,可能是因为.gitignore冲突,git有提示到git reset --hard这一句,以为是会重置(reset这英语),就选了另一项(忘了选了什么了),然后进行平常的pull,commit,提示pull到bitbucket成功了,但看代码却没有看到a所做的更改.没在意,b就继续修改代码,push到远程.b这边提示这个.
b以为自已看懂了,选择了$ git add --ignore-removal app/storage/sessions/
然后..上bitbucket一看,发现刚才a所做的更改全被删除了..
例如:像图片中这些是a加入的东西, 还有很多其他的代码,...现在全被删除掉了..
怎么恢复a成功push的更改,同时也保留b的这次更改呢? a的commit有160个文件改动,b的也有60多...除了a和b2人商讨根据代码一条条的对照思路进行恢复,有没有比较好的方案呢? 谢谢啦 ...
更新:
按照@nightire的回答, a这边进行了如下操作
# git add .# git commit -m 'big wrong! for last your git-commits'On branch php-v0.0.1Your branch is up-to-date with ’origin/php-v0.0.1’.nothing to commit, working directory clean
所以,a修改了一个文件,加了一个空行,然后重新# git push --force orgin php-v0.0.1:php-v0.0.1
接着,b这边进行如下操作
$ git pull origin php-v0.0.1:php-v0.0.1Password for ’https://Deloz@bitbucket.org’:remote: Counting objects: 15, done.remote: Compressing objects: 100% (6/6), done.remote: Total 6 (delta 4), reused 2 (delta 0)Unpacking objects: 100% (6/6), done.From https://bitbucket.org/deloz/xxxxx ! [rejected]php-v0.0.1 -> php-v0.0.1 (non-fast-forward) + c344522...14bd65e php-v0.0.1 -> origin/php-v0.0.1 (forced update)
好像b又操作错了,这分支好像不对呀,然后b又来了一次不加参数了pull,如下
$ git pullPassword for ’https://Deloz@bitbucket.org’:Merge made by the ’recursive’ strategy. app/database/migrations/xxxxxx.php | 1 + 1 file changed, 1 insertion(+)
此时,b这边仍然没有a加入的文件和a之前(b出错前,a修改并push成功的代码)的修改.(这次a是加了一个空行,b这边也成功反映出来了.)...
再更新:
根据大家的看法和方案a操作
# git log --pretty=oneline14bd65ee1b14c1f06be98b22bc6cb5feb2039656 big wrong! for last your git-commits3c96695b53f7d4e8dd78c9025044cea1d4cc0472 这个是正确的时候a所push的00f0cdd6b8861d64a7930b823f552888edebdc11 xxxxxxxxxx668fde30ad1d5d76b550f572ba6b64ae14a1e715 xxxxxx8a80bb0eb9387db68119bbd7e0d15677ed7aa1f1 xxxxx7ca8599be1ceb1dde6766315543209bf1bb761ce xxxxx^bba184c4f324ed99b3fb580c103aba3505a688a5 xxxxxxxxx458182037cfa54b8447b617c119d134ada250462 xxxxxxxxx0029b46ac999f2c4d59c8cfb194ed1c2653fa1f4 xxxxxxn
b使用了git revert commit,代码没回滚到正确的commit去..应该是用错了..
$ git log --pretty=oneline06661f005bc306796d2101633f68c2d01cd6bac3 re push (b push上来的)3e34c6f8c177c67d487c7858720ac383e77738e2 Revert 'Revert 'big wrong! for last you (b push上来的)bcf07a9836aaaa9bdd505094b0859c13322f4519 Revert 'big wrong! for last your git-co (b push上来的)885c117de5ef67f430e0d3f8b0b1647a1cd14ee8 Merge branch ’php-v0.0.1’ of https://bi (b push上来的)14bd65ee1b14c1f06be98b22bc6cb5feb2039656 big wrong! for last your git-commits(a加空行后 push上来的)c344522e2cba0e85e4b14393d596b992d47f1821 add column to table (b push上来的)3c96695b53f7d4e8dd78c9025044cea1d4cc0472 这个是正确的时候a所push的00f0cdd6b8861d64a7930b823f552888edebdc11 xxxxxxxxxx668fde30ad1d5d76b550f572ba6b64ae14a1e715 xxxxxx8a80bb0eb9387db68119bbd7e0d15677ed7aa1f1 xxxxx7ca8599be1ceb1dde6766315543209bf1bb761ce xxxxx^bba184c4f324ed99b3fb580c103aba3505a688a5 xxxxxxxxx458182037cfa54b8447b617c119d134ada250462 xxxxxxxxx0029b46ac999f2c4d59c8cfb194ed1c2653fa1f4 xxxxxxn
接着a执行
//备份一下当前a的分支# git branch php_backup//把a的分支回滚到 3c96695b53f7d4e8dd78c9025044cea1d4cc0472 因为上一次操作是 push --force了...# git reset --hard 3c96695b53f7d4e8dd78c9025044cea1d4cc0472HEAD is now at 3c96695 change some views//删除远程的bitbucket上的分支# git push origin :php-v0.0.1Password for ’https://deloz@bitbucket.org’:To https://deloz@bitbucket.org/deloz/xxx.git - [deleted] php-v0.0.1//把正确的3c96695b53f7d4e8dd78c9025044cea1d4cc0472, push到远程bitbucket上# git push origin php-v0.0.1Password for ’https://deloz@bitbucket.org’:Counting objects: 256, done.Delta compression using up to 2 threads.Compressing objects: 100% (220/220), done.Writing objects: 100% (256/256), 785.09 KiB | 0 bytes/s, done.Total 256 (delta 64), reused 158 (delta 26)To https://deloz@bitbucket.org/deloz/xxx.git * [new branch] php-v0.0.1 -> php-v0.0.1
然后, 根据@Guang Chen的方法, b操作
//备份一下B的分支$ git branch php_bbbb//把b的分支回滚到 3c96695b53f7d4e8dd78c9025044cea1d4cc0472$ git reset --hard 3c96695b53f7d4e8dd78c9025044cea1d4cc0472$ git fetch origin$ git rebase origin/php-v0.0.1//看一下log, b和a的一样的状态了.$ git log --pretty=oneline3c96695b53f7d4e8dd78c9025044cea1d4cc0472 这个是正确的时候a所push的00f0cdd6b8861d64a7930b823f552888edebdc11 xxxxxxxxxx668fde30ad1d5d76b550f572ba6b64ae14a1e715 xxxxxx8a80bb0eb9387db68119bbd7e0d15677ed7aa1f1 xxxxx7ca8599be1ceb1dde6766315543209bf1bb761ce xxxxx^bba184c4f324ed99b3fb580c103aba3505a688a5 xxxxxxxxx458182037cfa54b8447b617c119d134ada250462 xxxxxxxxx0029b46ac999f2c4d59c8cfb194ed1c2653fa1f4 xxxxxxn$ git statusOn branch php-v0.0.1Your branch is up-to-date with ’origin/php-v0.0.1’.nothing to commit, working directory clean
剩下的就是分支php_bbb里边的不同代码...使用git diff php-v0.0.1 php_bbbb >> 11.txt ,让b去修改了...(/ □ )
问题解答
回答1:你的b在pull origin master之前,是有一个commit的例如abcde
# 在b机器上$ git reset abcde --hard
回到b pull之前的样子然后因为你的a始终没有pull过,所以现在可以认为回到了你最初的样子,除了a提交的一个添加空行的提交
也就是说你现在应该和在2是一样的状态。这时你的b也是一个干净的工作区(没有unstaged change)如果你确信现在确实是和2中是一个状态,那么在b上执行
$ git fetch origin$ git rebase origin/php-v0.0.1
这时会提醒你有冲突,比如.gitignore然后打开.gitignore文件,解决冲突,再执行
$ git add .gitignore #添加解决了冲突的文件$ git commit #直接:wq即可
如果在rebase过程中,有什么意外情况,请不要随意操作,通过git rebase --abort放弃,然后再补充问题
回答2:我觉得没那么复杂啊……
A,本地的最近更新还是 OK 的吧?我的意思是在 B 最后 push 之后,A 没有 pull 吧?如果是这样,让 A 直接 push --force,覆盖掉 B 最后的 push,然后 B 重新 pull,这次不要弄错了,以后就好了。
如果 A 已经 pull 过最新的(也就是错误的)代码,那就在本地 reset 到原本应该正确的那里,然后重复上面的事情就好。
总而言之一句话,分布式的好处就是不管 central repo 乱成啥,你想要的那些 commits 总能找回来。
回答3:因为看晕了,也不太习惯git命令行,具体回答就不做了。
我只想说,这种场景下,git pull这条命令就不应该用,fetch & rebase才是正道
另外不如说,Git的使用姿势更有问题
两个人同时在一条分支里开发这件事有问题,大多数情况都应该是各自在各自的feature branch当中玩,自己的未完工的功能就应该在自己的分支里,拉别人的代码应该永远不影响自己的分支。一个commit超过10个文件有问题。或者从时间上看,超过半天的编码工作没有提交有问题比起解决现有代码乱掉(这是小事,总能解决的),团队内普及正确的git姿势才是更重要的
参考: 一种成功的Git分支模型 http://www.juvenxu.com/2010/11/28/a-successful-git-branching-model/