git 提交出现 detached head git提交冲突怎么解决决

我痛恨 Git 的 10 个理由 - 开源中国社区
当前访客身份:游客 [
当前位置:
我痛恨 Git 的 10 个理由
Git 是一个源代码版本控制系统,正在迅速成为开源项目的标准。它有一个强大的分布式模型,允许高级用户用分支来处理各种棘手的问题和改写历史记录。但是,要学习 Git 是需要付出更多的努力,让人不爽的命令行接口以及 Git 是如此的忽视它的使用者。
下面是我为什么如此痛恨 Git 的 10 个理由:
1. 复杂的信息模型
Git 的信息模型是很复杂的,而且你必须对他们都很了解。在这个方面上你看看 Subversion:有文件、工作目录、资源库、版本、分支和标签。你需要了解的就是这些东西,实际上,分支、标签和文件你已经了解,但如果使用 Git ,你拥有更多的概念需要了解:文件、工作树、索引、本地资源库、远程资源库、远程、提交、treeishes、分支和 stash。你需要了解比 Subversion 更多得多的知识点。
2. 让人抓狂的命令行语法
Git 的命令行语法完全是随意的而且不一致,例如 git pull 基本上跟 git merge 和 git fetch 一样,git branch 和 git checkout 合并就变成 git checkout -b,git reset 命令的不同参数做的事情完全不一样,指定文件名后命令的语义完全不同等等。
而最为壮观的就是 git am 命令了,据我所知,这是因为 Linus 在当年某个晚上为了解决通过电子邮件阅读补丁而使用的不同的补丁语法,特别是在邮件的标题上。
3. 蹩脚、让人费解的文档
说起 Git 的这个文档,我唯一想说的就是&操&。他们是为计算机科学家在写文档,而不是用户。在这里举个例子:
git-push & Update remote refs along with associated objects
如果是针对用户而言,应该描述为:
git-push & Upload changes from your local repository into a remote repository
另外一个例子:
git-rebase & Forward-port local commits to the updated upstream head
翻译: git-rebase & Sequentially regenerate a series of commits so they can be applied directly to the head node
4. 信息模型的扩散
刚才我在第一点提到的 Git 的信息模型是非常复杂的,而且还想癌细胞一样一直在扩散,当然一直在使用 Git ,就会不断的冒出各种新的概念,例如 refs, tags, the reflog, fast-forward commits, detached head state (!), remote branches, tracking, namespaces 之类的。
5. 漏洞百出的抽象
Git 包含太多不是抽象的抽象,在定义用户接口和实现上经常没有任何区别,这是可以理解的,对一个高级用户来说他需要了解一些功能的具体实现,以掌握各个命令的微妙之处。但大量的内部细节对初学者来说简直是噩梦。有这么一个说法,关于水暖器材和瓷器,但你必须成为一个水暖工才能知道器材如何安装在瓷器上。
很多人对我的抱怨予以回应说:你无需使用所有的命令,你可以向 Subversion 一样来使用 Git。这是狡辩,就好比是告诉一个老奶奶说高速公路并不可怕,她可以在高速路上靠左边的快车道上以时速 20 公里爬行,一样的道理。Git 并没有提供任何有用的子集,每个命令都会连带着对其他命令的要求,很简单的动作经常需要很复杂的动作来撤销或者改进。
下面是一个 Github 项目维护者的一些善意的建议:
在分支和 master 上寻找合并的基准: &git merge-base master yourbranch&
假设你已经提交了更改记录,从对你的提交重新基准化到合并准,然后创建一个新分支
git rebase &onto &basecommit& HEAD~1 HEAD
git checkout -b my-new-branch
检出你的 ruggedisation 分支,然后移除提交: &git reset &hard HEAD~1&
合并新的分支到 ruggedisation: &git merge my-new-branch&
检出 master (&git checkout master&), 合并新分支 (&git merge my-new-branch&), 然后检查合并后的情况,接着移除合并 (&git reset &hard HEAD~1&).
提交新的分支 (&git push origin my-new-branch&) 并记录 pull 请求
翻译:&奶奶,在高速公路上开车很容易的。松开离合器,让转速超过 6000 转使车轮打滑,然后进入第一个弯道并上高速公路,看路牌到出口前,使用手刹漂移转向出口。
6. 维护简单,但是提交麻烦
Git 很强大的一点就是代码基准库的维护,你必须合并来自大量不同源的提交,非常适合大规模并行开发。但是这些都不是为大多数 Git 的用户设计的,他们只是需要编写代码,可能好几个月都在同一个分支上,对他们来说 Git 是带有 4 个手柄的双锅的咖啡机,但用户只想立即喝到咖啡。
有趣的是,我并不认为这是 Git 在设计中做的权衡。它完全是忽视了真正的用户需求、混淆架构和接口。如果你是一个架构师,那么 Git 是很棒的。但对用户来说它很糟糕,已经有不少人在为 Git 编写一些简化的接口,例如 easygit。
7. 不安全的版本控制
作为一个版本控制系统而言,它必须承诺的就是:一旦代码提交到系统,那么我将保证代码的安全,你做的任何改动你都可以找回。而 Git 食言了,有很多方法可以让整个资料库完全崩溃而且不可恢复:
git add . / & / git push -f origin master
git push origin +master
git rebase -i &some commit that has already been pushed and worked from& / git push
8. 将版本控制库维护者的责任移给贡献者
在传统的开源项目中,只需要一个人负责处理分支和合并这样复杂的操作,那就是维护者。而其他人只需要简单的更新提交、更新提交、不断的更新提交。而现在 Git 让每个用户都需要了解作为维护者才需要知道的各种操作,烦不胜烦。而维护者呢,无所事事,翘起二郎腿喝咖啡。
9. Git 的历史是一堆谎言
开发工作主要的产出就是源代码,一个维护良好的代码历史就对一个产品来说非常的重要,关于重新基准化有很多的争论,多数是依赖于对凌乱合并和不可读的日子的审美判断。而重新基准化为开发者提供一个&干净整洁&的却毫无用途历史记录,而实际上正确的解决方法是更好的日志输出以及对不想要的合并进行过滤。
10. 简单任务也要诸多命令
如果你在开发一个开源项目,你做了一些改变,然后想与其他人分享,你只需要:
执行 svn commit
如果你增加了一些新文件:
svn commit
如果你的项目托管在 Github 类的网站中,那么你需要:
Make some changes
git add [not to be confused with svn add]
git commit
到此为止,你的更改只完成了一半,接下来你需要登录到 Github,查找你的提交,然后发布一个 &pull request& ,这样其他人才可以获取你的改动
在现实中,Github 的维护者希望你的改动是功能方面的分支,他们会要求你这样操作:
git checkout master [to make sure each new feature starts from the baseline]
git checkout -b newfeature
Make some changes
git add [not to be confused with svn add]
git commit
然后登录到 Github,切换到你的新特性分支,发布 &pull request&
为了将你的更改从你的本地目录中移到实际的项目资源库,你需要:add, commit, push, &click pull request&, pull, merge, push.
下面是一个流程图向你展示一个典型的开发者在 Subversion 上要做的工作:
"Bread and butter" 是与远程 SVN 资料库操作的命令和概念。
然后我们再来看看如果你的项目托管在 Github 上会是怎样的:
如果 Git 的强大之处是分支和合并,那么它的弱点就是让简单的任务变得非常复杂。
翻译自: ,转载请注明:
文章出处:
Git 的详细介绍:
Git 的下载地址:
想通过手机客户端(支持 Android、iPhone 和 Windows Phone)访问开源中国:
旧一篇: 4年前
新一篇: 4年前
相关讨论话题
你也许会喜欢
没人评论?
2楼:Master.fm
有同感 ,我也是这么认为了 ,小团队svn就够用了
3楼:cers000
版本控们在哪里?
4楼:地皮鼠
痛恨就不用
5楼:keengo
什么东西有优点和缺点,看你站在什么角度。相同的东西,不同的角度得出不同的结论。一句话:适合自已的就是最好的。
6楼:吴冠中
把简单的事变复杂,没意思,Svn都用不上,别提git了
看来需要一个Git和SVN综合体
8楼:Wanghao
Git本身就不是一个产品,它只是linus等开发人员协作开发的工具,所以它的目标不是让所有人用着舒服,而是能让他们更好的工作罢了,
9楼:Java行者
别的观点也不加评论,简单说说对第3点的看法:蹩脚、让人费解的文档;一个错误的论点在IT界蔓延,这个论点有苹果创造,每个人都觉得自己是用户,什么东西做的用户体验差,就说跟苹果学学用户体验,麻痹的,我看到这就想吐!用git的哪一个是TM的用户,连程序说明式的用法都看不懂,你用什么版本控制啊?你有毛病啊?你使用了版本控制系统,你就不在是一个用户!没听说哪个没任何计算机背景的人用git,或者说版本控制!情绪有点激动了,但是这篇文章的作者确实欠骂!在你使用任何一个工具前,请你思考:你是不是所谓的用户?苹果的任何一款产品都是将用户当SB的,所以那样的用户才是真正的用户,当你能对一个产品说出个科学的东东,你就不再是用户!
10楼:Java行者
引用来自“Java行者”的评论别的观点也不加评论,简单说说对第3点的看法:蹩脚、让人费解的文档;一个错误的论点在IT界蔓延,这个论点有苹果创造,每个人都觉得自己是用户,什么东西做的用户体验差,就说跟苹果学学用户体验,麻痹的,我看到这就想吐!用git的哪一个是TM的用户,连程序说明式的用法都看不懂,你用什么版本控制啊?你有毛病啊?你使用了版本控制系统,你就不在是一个用户!没听说哪个没任何计算机背景的人用git,或者说版本控制!情绪有点激动了,但是这篇文章的作者确实欠骂!在你使用任何一个工具前,请你思考:你是不是所谓的用户?苹果的任何一款产品都是将用户当SB的,所以那样的用户才是真正的用户,当你能对一个产品说出个科学的东东,你就不再是用户!情绪有点激动了,请大家原谅
11楼:zhaoyou
还是支持git!
12楼:胡晅晖
确实有一些困扰,我只是简单用了一下,团队的应用还没建设起来
10:36 (非会员)
整一篇就是说git命令复杂,而且没有什么说服力,在中国这种网络环境,svn用的你想哭…git事实上真的不需要了解太多命令,作者完全在误导或诋毁git
14楼:fuhaiping
一直都在用git,感觉也挺好的,感觉作者说的有点偏激了
15楼:surgesoft
我觉得osc上有各种不同观点甚至对立观点的文章,这个很好。。对于GIT,我的意见是爱而知其恶,憎而知其善。但是就我个人而言,GIT感觉上还是很简单的,
16楼:特劳特
git很不错啊,用egit的飘过
17楼:游客
用不着痛恨 吧。
18楼:mallon
反正我不喜欢git,违背了kiss原则
19楼:开心303
这正是我喜欢git的是个理由。
20楼:李斌.北界.upsilon
git flow好像被那啥了?
与内容无关的评论将被删除,严重者禁用帐号
本周热点资讯
本站最新资讯114网址导航Git笔记(一)——[commit, checkout] // 进击的马斯特
其实一直觉得自己是会用Git的,毕竟咱也是用Github的人啊!可是三月份找工作时候的一次面试颠覆了我的看法:
Q: 用过Git吗?平常怎么用的?A: 用过的,一般就是add,commit,push嘛Q: branch用的多吗?git rebase这命令使用过吗?A: 一般都是自己的项目用的,就一个人,没涉及到这么复杂的使用Q: 那换个话题吧。。。
这么一搞才发现,其实我只会皮毛啊。。。正好现在新公司是用Git的,我也趁机恶补一下!本文其实就是对这篇文章的一个实践。
谈到Git,最先需要明确的就是这三个概念:
Working Directory:工作目录,这个可以简单的理解为你在文件系统里真实看到的文件
Stage(Index):暂存“目录”,用git add命令添加的文件就到了这里,即将被commit的文件
Repository:项目“目录”,用git commit提交的文件就到了这里
后两个“目录”之所以加上引号,是因为其实它们并不是真实存在于文件系统中的目录,是个抽象的概念!为了方便后面的表述,我们就动手建立一个Git工程,并添加一个test.txt的文件。
1234mkdir GitNotescd GitNotesgit inittouch test.txt
为了更直观的观看,后续将采用这个软件来讲解。将这个目录添加到SourceTree中可以看到:
从图1中我们可以直观的看到三个目录,其中区域1即为Repository目录,默认显示的是所有commit的log记录,由于我们还没有进行commit,所以此时看到的就是ncommitted changes。区域2的标题为Staged files,就是Stage目录,目前我们没有git add,所以这里是空的。区域3就是Working目录,与文件系统对应的,我们新建的文件test.txt就在这里,可以看到前面有个问号,表示Not Tracked,就是说这个文件从来没有被add过。
有了这些基本概念,我们来做第一次commit吧,看看文件是怎么在这三个目录下转移的吧。运行git add test.txt,观察SourceTree的面板,发现文件test.txt已经来到了区域2,如图2。运行git commit -m &add test file&,文件已经到达了区域1。点击区域1的commit message,即可看到文件。标签master表示我们当前处于master分支,最新的commit为“add test file”,这个commit可以用cde6c09来唯一的标识。
commit - 我会好几种姿势呢
前面的第一次提交用的是比较常规的姿势,其实提交代码还有好多种姿势哦!我们对test.txt文件做一下简单的修改,加一行“test 1”,然后运行git commit -am &commit 1&,通过加-a参数,和先运行git add .再commit的效果是一样的,也就是文件直接从Working目录到了Repo里。换个姿势再来一次,给文件加一行“test 2”,然后运行git commit test.txt -m &commit 2&,这次文件也是从Working直接到Repo去了。我们还可以再换个姿势,给文件再添加一行“test 2.5”,运行git commit --amend -am &commit 2, 2.5&,观察SourceTree,发现提交最后的一次提交记录被修改了,并且包含了最近的两次更改,如图3所示。
总结一下commit的几种姿势:
传统姿势:先git add file再git commit -m &xxx&
快速提交当前所有文件的更改:git commit -am &xxx&会先add所有的更改然后提交
快速提交单个文件的更改:git commit file -m &xxx&只提交这个文件的更改
修改最后一次提交:git commit --amend -am &xxx&将当前的更改加入最后一次commit中并更改最后一次commit的信息。其实观察可发现新的commit是替换了原先的commit,因为commit的hash已经变了。
关于commit还有几点想说的:
git commit -a和git commit file这两个命令对Untracked的文件是无效了,也就是说只对add过的文件的更改才有效。比如我们新建一个文件touch test1.txt,然后运行git commit -am &add test1&或git commit test1.txt -m &add test1&都是无效的,如图4所示。
尽量不要使用-m标签,-m标签只适用于单行的提交信息,而提交信息最好越详细越好,方便别人,更方便自己。举个例子,给test.txt添加一行“test 3”,运行git add test.txt,再运行git commit,这时会打开Git中默认的编辑器(一般是vim),推荐像图5这样添加commit信息。其中第一行是简短的信息,第三行是详细的解释,标准就是第一行一目了然,第三行越详细越好。这样做的另一个好处是,Github默认是支持这种书写方式的,在Github的pull request里,默认显示第一行,第三行被折叠,非常方便。并且如果你的pull request只包含这一个commit的话,Github会默认将第一行作为标题,第三行作为内容,如图6。
尽量也不要使用git add .或git commit -a,这两条命令都会将当前所有的更改进行Stage或commit,这表面看来没什么大问题,其实是很危险的,有的时候会将未注意的更改错误的提交。Git的最佳实践还是强调小步提交,也就是说提交频繁一点,每次提交包含的更改少一点,这样不仅方便跟踪,更能避免多人合作时产生冲突。使用SourceTree这样的工具可以做到行级别的提交,也就是说一个文件我修改了好多行,可以把这些更改放到不同的commit里去。比如,修改test.txt添加两行“test 4”和“test 5”,然后打开SourceTree观察,如图7所示,点击一行后,右上角的“Stage lines”图标就会出现,这个图标的作用就是将这一行更改进行add。用这种方法,我们可以把这两行作两次提交。最终结果如图8所示。
checkout - 上得了厅堂,下得了厨房
哟哟切克闹,煎饼果子来一套!说到了吃,git checkout可以说是身兼多职——上得了厅堂,下得了厨房。一个是分支相关的操作,另一个是可以恢复文件到之前的某个状态。
平常最常用的功能就是创建和切换分支了。运行git checkout -b branch1新建一个名为“branch1”的分支并切换过去。给test.txt再添加一行“test 5.5”,做一次commit,git commit test.txt -m &commit 5.5&。这时的状态如下图:
可以看到当前的分支上有个小对号,当前所处的commit前面的圆点是白色的。此时运行git checkout master就会切回master分支。“master”这个位置不仅可以放分支的名称,还可以放commit的hash。比如git checkout cc59b55(commit 2,2.5所对应的hash),这个时候Git会给出提示信息,如下图:
此时Git处在Detached HEAD状态,从SourceTree里也可以看出有一个HEAD的tag指向对应的commit。HEAD可以理解为时一个指针,指向当前所在的分支当前的commit。其实这个时候Git处在一个“游离的匿名分支”上,Git提示说你可以做修改,做提交,但一旦你checkout到别的地方,这些提交将无法再引用到,如果你想保存,必须在此基础上创建一个新的分支。什么意思呢?我们跟着提示一步一步做。首先给test.txt文件(此时文件只有三行,最后一行是test 2.5)再添加一行“test aaa”并提交git commit test.txt -m &commit aaa&。这时,看一下SourceTree的状态图:
按照Git给的提示,此时我们checkout到别的地方去:git checkout master切回master分支,再去SourceTree看一眼,我擦泪,刚才的修改丢了!!如下图:
不听“提示”言,吃亏在眼前,难道真的像提示说的那样,刚才的修改再也找不到了吗?非也,只要记得commit的hash,我们是可以切回去,从图11中找到commit aaa所对应的hash,运行git checkout 6382c7d,再看看SourceTree,OK,都回来了!“游离的匿名分支”的取名就来源于此,这些commit目前不属于任何分支,不能通过切分支的方式找到他们,只能记住hash才能切回来。为了保存这些提交,我们按照提示新建一个分支:git checkout -b branch2。这样以后就可以通过git checkout branch2切到该分支找到这些提交了。
除了分支相关的操作,checkout的另一个作用就是恢复文件了。既然说到恢复,那肯定有source(从哪里恢复)和target(恢复到哪里去),个人感觉一般checkout的target就是指你的工作目录,而source自然是其他两个目录了。也就是说,可以从暂存目录往工作目录里恢复文件,也可以从Repo里的各个commit记录里往工作目录恢复文件。为了方便讲解,我们先切回master分支:git checkout master,然后给test.txt加一行“test temp”,这个时候可以在SourceTree里看到存在Uncommited changes,运行git checkout -- test.txt,可以看到刚才的更改被取消了,也就是说我们从Repo的最新commit里将test.txt恢复到了我们的工作目录里。这里的--符号主要是为了避免歧义,其实这里我们不要--,直接运行git checkout test.txt也是可以的,但试想这么一种情况:我们的文件名称与分支名称一样,比如有一个叫做“master”的文件,如果不加--则Git会认为你想切换分支,所以必须使用--来告诉Git你想恢复文件而不是切换分支,多才多艺的人就是这样闹心啊!我们重复同样的操作,给test.txt添加一行“test temp”并做add操作:git add test.txt,这样文件就到了暂存目录。这时候运行git checkout test.txt是没有作用的,因为你的工作目录和暂存目录是一样,继续更改test.txt,添加一行”test temp1”并保存,这里运行git checkout test.txt,则会发现新加的这一行temp1没有了,也就是暂存目录被恢复到工作目录了。实践了“Repo最新commit =& 工作目录”和“暂存目录 =& 工作目录”,下面试试历史commit作为source吧。为了方便,将当前暂存区的更改(“test temp”)进行提交:git commit -m &commit temp&,此时的commit记录如下图:
这里我们试着将某个历史commit的test.txt恢复回来,比如将commit 3状态下对应的文件恢复,则找到对应的commit hash,运行git checkout 9fc9896 test.txt,会发现当前工作目录最后一行已经是“test 3”了,与commit 3时的文件状态一致,并且这个更改(最新的commit与commit “test 3”的差别)已经自动被add到暂存区域,如下图:
运行git reset HEAD test.txt(git add的反操作,后面会讲)和git checkout test.txt(最新的commit恢复到工作目录)来使test.txt恢复到“test temp”的状态。除了hash,还可以使用一些“快捷方式”来引用各个commit,比如刚才的操作用git checkout HEAD~3 test.txt也是一样的,其中HEAD~3表示比当前的commit早3个commit(爷爷的爸爸。。。)。说到快捷方式,其实分支名称也可以理解成一个快捷方式,代表所在分支的最新commit。比如运行git checkout branch2 test.txt,同样可以看到branch2的最新commit的状态被恢复到工作目录并添加到了暂存区。
总结一下checkout的几个功能:
分支相关操作:git checkout 分支名/commit hash切换到相应的分支或commit,加上-b参数则会创建分支并切换过去
恢复文件相关操作:git checkout [分支名/commit hash/HEAD快捷方式] -- 文件名恢复指定分支的最新commit或指定commit或快捷方式指向的commit的文件到工作目录,若省略中间的参数,则
暂存区有内容且暂存区内容与工作目录不同,则恢复暂存区的状态到工作目录
暂存区无内容,则恢复HEAD(最新的commit)的状态到工作目录
P.S. 本来准备把所有命令写在一篇里,不过感觉篇幅太长了也不好,这篇就到这里吧,剩下的下篇再写。
前端 | 溜冰 | Mac关于git使用中Detached&HEAD
首先,来看一下git的原理。
上面的四条命令在工作目录、暂存目录(也叫做索引)和仓库之间复制文件。
add&files&把当前文件放入暂存区域。
git commit&给暂存区域生成快照并提交。
--&files&用来撤销最后一次git
add&files,你也可以用git
reset&撤销所有暂存区域文件。
git checkout
--&files&把文件从暂存区域复制到工作目录,用来丢弃本地修改。
你可以用&git reset
-p,&git checkout -p,
or&git add -p进入交互模式。
也可以跳过暂存区域直接从仓库取出文件或者直接提交代码。
git commit
-a&相当于运行&git
add&把所有当前目录下的文件加入暂存区域再运行。git
commit&files&进行一次包含最后一次提交加上工作目录中文件快照的提交。并且文件被添加到暂存区域。
git checkout HEAD
--&files&回滚到复制最后一次提交。
Checkout解决办法
checkout命令用于从历史提交(或者暂存区域)中拷贝文件到工作目录,也可用于切换分支。
当给定某个文件名(或者打开-p选项,或者文件名和-p选项同时打开)时,git会从指定的提交中拷贝文件到暂存区域和工作目录。比如,git
checkout HEAD~
foo.c会将提交节点HEAD~(即当前提交节点的父节点)中的foo.c复制到工作目录并且加到暂存区域中。(如果命令中没有指定提交节点,则会从暂存区域中拷贝内容。)注意当前分支不会发生变化。
当不指定文件名,而是给出一个(本地)分支时,那么HEAD标识会移动到那个分支(也就是说,我们“切换”到那个分支了),然后暂存区域和工作目录中的内容会和HEAD对应的提交节点一致。新提交节点(下图中的a47c3)中的所有文件都会被复制(到暂存区域和工作目录中);只存在于老的提交节点(ed489)中的文件会被删除;不属于上述两者的文件会被忽略,不受影响。
如果既没有指定文件名,也没有指定分支名,而是一个标签、远程分支、SHA-1值或者是像master~3类似的东西,就得到一个匿名分支,称作detached
HEAD(被分离的HEAD标识)。这样可以很方便地在历史版本之间互相切换。比如说你想要编译1.6.6.1版本的git,你可以运行git
checkout v1.6.6.1(这是一个标签,而非分支名),编译,安装,然后切换回另一个分支,比如说git
checkout master。然而,当提交操作涉及到“分离的HEAD”时,其行为会略有不同
也就是说,如果你不是为了测试git,那么你最好使用
的方法,或者用
checkout -b
的方法,而不是直接checkout。
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。3563人阅读
linux(7)
1. 在本地可以建任意分支,只要不往服务器git push就不影响服务器的内容。
2.在使用git push的时候,如下:
git push file:////home/hebo/work/testgit/ master
这样对本地的修改,只会master分支推送到服务器上,其它的不影响
但是如果需要把其它的本地维护的分支推送到服务器,需要
git push file:////home/hebo/work/testgit/ local_hebo,本地也必须存在local_hebo的分支
1.为什么在自己建的git工程中,可以使用git branch查看分支,而在android的工程中使用git branch查看的分支为空?
2.为什么自己无法建立remote/umg/froyo这样子的分支,而android可以
3.repo init -u git:///manifest -b froyo -m prod-bb表示什么?
使用以上例子做如下实验:
1.& git init m2doc
创建一个空的m2doc库,以做实验用ll查看,可以看到只有一个.git目录。
2. git remote add hb /home/hebo/work/test_hebo_git/m2doc.git/
添加一个远程仓库的标签,用此标签进行管理,可以使用git remote show查看,生成了一个hb的远程仓库在本地的标签,使用git remote show hb查看,生成如下信息,此时show命令会通过网络与远程仓库通信:
* remote hb
& Fetch URL: /home/hebo/work/test_hebo_git/m2doc.git/
& Push& URL: /home/hebo/work/test_hebo_git/m2doc.git/
& HEAD branch: master
& Remote branches:
&&& local_sub_local new (next fetch will store in remotes/hb)
&&& master&&&&&&&&& new (next fetch will store in remotes/hb)
此信息表示, 抓取的远程的地址,HEAD分支,相当于master分支,远程存在local_sub_local分支,以及存在master分支,如果使用git clone会自动创建一个original的标签
3. git fetch hb
从远程仓库同步抓数据到本地的仓库,本地建立了一个和远程仓库完全一样的镜象。
remote: Counting objects: 686, done.
remote: Compressing objects: 100% (663/663), done.
Receiving objects: 100% (686/686), 1020.29 KiB, done.
remote: Total 686 (delta 132), reused 0 (delta 0)
Resolving deltas: 100% (132/132), done.
From /home/hebo/work/test_hebo_git/m2doc
&* [new branch]&&&&& local_sub_local -& hb/local_sub_local
&* [new branch]&&&&& master&&&& -& hb/master
此时,才真正从远程仓库取数据下来同步到本地的仓库,可以看到 local_sub_local对应远程的 hebo/local_sub_local,master对应的远程下的hb/master
4.使用git checkout hb/local_sub_local
会出现如下提示Note: checking out 'hb/local_sub_local'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
& git checkout -b new_branch_name
表示当前处于&detached HEAD&的状态,在此状态可能查看,实验,用git branch
可以看到出现如下提示:* (no branch),表示本地还没有确定的分支。
5. git checkout local_sub_local
从本地库拉出一个local_sub_local分支,使用 git branch
* local_sub_local
可以看到当前处于 local_sub_local的分支。
6. git checkout master
从本地拉出一个master的分支,使用git branch
& local_sub_local
可以看到当前处于master的分支,本地有local_sub_local以及master两个分支
7.& git checkout hb/master
从本地拉出一个空分支,此分支是临时的,本地的修改无法保存。
再次使用git checkout hb/master,然后通过git branch
* (no branch)
& local_sub_local
可以看到当前双处于远程的no branch分支。
8. git diff的使用
git diff是一个强大的比较版本的工具,可以对本地与本地缓存,远程分支,tags标签进行比较
例如: git diff --stat remotes/umg/froyo-stable remotes/umg/froyo-prod-bb
&&&&&&&&&&&& 别外可以使用git diff sha1 sha2 path比较某个目录下的不同,也可以在某个目录下使用 git diff& --relative比较当前目录下的不同文件。
&&&&&&&&&&& 可以在一个工作树中使用git diff进行比较,也可以在一个仓库中直接使用git diff branch_name1 branch_name2进行比较,比较是基于
&&&&&&&&&&& 仓库的,其本质是都是基于HASH值,如果本地的仓库没有更新,是无法比较本地创库没有,而远程创库有的更新的节点的。
&由此引申开来,此质的remote/umg/branch_name其实对应的是本地的仓库,只要在使用git remote show orginal的时候,才会发起网络连接,可以看到远程是否有更新。如果有更新,会显示 (next fetch will store in remotes/umg)
9. 对于存在分支与本地目录同名的的信息
可以使用git diff master test3 --
在test3后面加一个--表示这是一个分支,而不是一个路径
10. git&rev-parse&命名是一个底层命令,我们偶尔要将某些称谓翻译成对象名的时候非常有用。&
$&git&rev-parse&origin
e05db0fd4f31ddef96b360d05984b
用此可以得到分支分支,tag对应的HASH值。
11. git diff的使用
Git 比较不同版本文件差异的常用命令格式:
git diff & & & & & & & & &&&&&&&&&&&&&&&&&&&&& 查看尚未暂存的文件更新了哪些部分
git diff&filename&查看尚未暂存的某个文件更新了哪些
git diff –cached&&&&&&&&&&&&&&&&&&& 查看已经暂存起来的文件和上次提交的版本之间的差异
git diff –cached&filename&查看已经暂存起来的某个文件和上次提交的版本之间的差异
git diff ffd98b291e0caa6c5eae661ce40c9 b8e7b00c02b95b320f14b625663fdecf2d63e74c 查看某两个版本之间的差异
git diff ffd98b291e0caa6c5eae661ce40c9:filename b8e7b00c02b95b320f14b625663fdecf2d63e74c:filename 查看某两个版本的某个文件之间的差异
12. git checkout
&&&&& 在git branch new_branch之后,git checkout new_branch相当于从本地当前分支上建立分支,工作树中的内容与当前的分支一致,如果要更新内容,需要从远程分支中merge到当前的分支,git merge origin/branch_name,&如果new_branch名与remote中的一致,在git remote show origin的时候,可以看到
&Local branch configured for 'git pull':
&&& master merges with remote master
& Local refs configured for 'git push':
&&& hb&&&& pushes to hb&&&& (up to date)
&&& master pushes to master (up to date)
如果当前的new_branch名与remote中的不一致,在git remote show origin的时候,可以看到:
& Local branch configured for 'git pull':
&&& master merges with remote master
& Local ref configured for 'git push':
&&& master pushes to master (up to date)
可以看到,此时新的分支不能直接push到服务器上
如果是通过git checkout -track origin/branch_name,此命令相当于git checkout -b branch_name origin/branch_name,
& Local branches configured for 'git pull':
&&& hb&&&& merges with remote hb
&&& master merges with remote master
& Local refs configured for 'git push':
&&& hb&&&& pushes to hb&&&& (up to date)
&&& master pushes to master (up to date)
如果 git checkout -b new_bracn origin/branch_name,此时会显示,another_branch不会直接push到服务器。
&Local branches configured for 'git pull':
&&& another_branch merges with remote hb
&&& hb&&&&&&&&&&&& merges with remote hb
&&& master&&&&&&&& merges with remote master
& Local refs configured for 'git push':
&&& hb&&&& pushes to hb&&&& (up to date)
&&& master pushes to master (up to date)
13. git show-ref
&List references in a local repository 浏览在本地仓库的引用。
14. git var
&Show a git logical variable 加-l参数显示本地的逻辑变量.
15. 使用如下方法,fetch到的数据,与repo抓到的一样,
git init bionic
cd bionic/
git remote add hb git://shumg001./a/aosp/platform/bionic.git
git fetch hb
输出结果:
emote: Generating pack...
remote: Done counting 6707 objects.
remote: Deltifying 6707 objects...
remote:& 100% () done
remote: Total 6707 (delta 4616), reused 6446 (delta 4420)
Receiving objects: 100% (), 2.55 MiB | 156 KiB/s, done.
Resolving deltas: 100% (), done.
From git://shumg001./a/aosp/platform/bionic
&* [new branch]&&&&& froyo-integ-mfld -& hb/froyo-integ-mfld
&* [new branch]&&&&& froyo-integ-pr1 -& hb/froyo-integ-pr1
&* [new branch]&&&&& froyo-integ-sr -& hb/froyo-integ-sr
&* [new branch]&&&&& froyo-prod-bb -& hb/froyo-prod-bb
* [new tag]&&&&&&&& android-sdk-2.0.1_r1 -& android-sdk-2.0.1_r1
&* [new tag]&&&&&&&& android-sdk-2.1_r1 -& android-sdk-2.1_r1
&* [new tag]&&&&&&&& android-sdk-tools_r2 -& android-sdk-tools_r2
remote: Generating pack...
remote: Done counting 5 objects.
remote: Deltifying 5 objects...
remote:& 100% (5/5) done
remote: Total 5 (delta 2), reused 5 (delta 2)
Unpacking objects: 100% (5/5), done.
From git://shumg001./a/aosp/platform/bionic
&* [new tag]&&&&&&&& android-2.0_r1 -& android-2.0_r1
&* [new tag]&&&&&&&& android-sdk-2.0_r1 -& android-sdk-2.0_r1
&* [new tag]&&&&&&&& android-sdk-tools_r3 -& android-sdk-tools_r3
&* [new tag]&&&&&&&& android-sdk-tools_r4 -& android-sdk-tools_r4
&* [new tag]&&&&&&&& android-sdk-tools_r5 -& android-sdk-tools_r5
在refs的目录下,会生成remote/hb/分支名, 以及tags/tag名,HEAD文件的内容指向ref: refs/heads/master.
使用git checkout --track hb/froyo-prod-bb可以在本地生成与分支froyo-prod-bb同名的本地分支,使用git checkout -b my_topic hb/froyo-prod-bb生成一个本地的分支,
可以使用git remote show branch看其与远程分支的相关性,如下所示:
Local branches configured for 'git pull':
&&& froyo-prod-bb merges with remote froyo-prod-bb
&&& my_topic&&&&& merges with remote froyo-prod-bb
& Local ref configured for 'git push':
&&& froyo-prod-bb pushes to froyo-prod-bb (up to date)
注意:出现此问题的原因是,在本地将一个git工程拷贝过来,然后以此工程为基础,然后clone过来,由于本地只有my_topic所以clone过来的只有一个my_topic分支,此处不会再clone服务器远端的分支,克隆是相对的,对于克隆来说,只有一个父,而与其父亲的父亲没有关系。
&16. 使用git cat-file与git ls-tree查看当前checkout出来的文件对应的是哪一个提交
假如想通过git checkout HEAD^^ . 将当前的目录回退到之前某一个版本,然后想知道具体回到了哪个版本,可以使用如下方法尝试:
i. 通过git log查看commit的SHA值 
ii.通过git cat-file commit SHA-ID找到对应的tree , parent的SHA-ID
iii.通过git ls-tree 查看SHA-ID,就可以找到当前tree下此文件的blob SHA-ID
iv.通过git ls-files -s可以当前路径下件下暂存文件的SHA-ID,这样就可以知道checkout出来的是哪一个文件
但一般如果需要回退文件,不通过此方法,通过branch回退版本,然后进行比较
例如:我想回到上几个修改,可以git checkout -b my_topic_xxmonth_xxday_xxhour_xxminute SHA_ID,这样在此分支上进行验证,然后通过git log就可以知道在哪个log的状态上了。
原文转自:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:86346次
积分:1023
积分:1023
排名:千里之外
转载:54篇
(1)(1)(1)(2)(1)(1)(1)(4)(1)(4)(6)(4)(3)(1)(1)(1)(3)(4)(1)(5)(5)(4)(3)

我要回帖

更多关于 git 提交失败 解决 的文章

 

随机推荐