git 总结 -- 本地操作篇
参考
http://rogerdudler.github.io/git-guide/index.zh.html
http://www.cnblogs.com/craftor/archive/2012/11/04/2754140.html
http://blog.csdn.net/hudashi/article/details/7664631/ rebase
git分类之前写过几篇文章,是基础但是感觉比较乱。这里做一下总结,先从本地库开始吧。
基础操作
本地仓库维护3课树, working dir, stage, HEAD分别代表工作区,缓存区和最后一次提交的版本。
git add 把工作区的内容加入缓存区,
git commit 把缓存区的内容加入到版本区并形成为最后一次的提交版本
# 从当前分支checkout一个新分支feature,并切换到新分支。
git checkout -b feature
# 从指定分支上checkout一个新分支feature, 并切换到新分支。
git checkout –b feature [branchname]
# 切换到指定分支
git checkout branchname
# 查看分支和删除
-a : 列出本地和远程的所有分支
-d : 删除分支
-D : 强行删除分支
# 重命名分支:
git branch –m oldname newname
-m不会覆盖已有分支名称,即如果名为newname的分支已经存在,则会提示已经存在了。
如果改成-M就可以覆盖已有分支名称了,即会强制覆盖名为newname的分支,这种操作要谨慎。
# 分支比较
git diff [branchname]如果没有指定分支名,则是工作区和缓存区的比较。
如果指定分支名,表示当前分支和指定分支所有文件进行比较
# stage
git add <filename>git add . | -A | *
git commit -m "message for code"
如果发现改动有误,某个文件需要退回到HEAD时的状态,
git checkout -- <filename>
此命令会使用 HEAD 中的最新内容替换掉你的工作目录中的文件。已添加到暂存区的改动以及新文件都不会受到影响。
Merge合并操作
一般都是往主分支master上合并。git checkout master
# 执行merge时,是把branchname的分支合并到当前分支。
git merge branchname
可能会出现冲突(conflicts),这时就需呀我们解决冲突,此时用 git diff 来查看合并到当前分支时的冲突情况,解决之后 git add 和 git commit。
<<<<<<<标记冲突开始,后面跟的是当前分支中的内容。
HEAD指向当前分支末梢的提交。
=======之后,>>>>>>>之前是要merge过来的另一条分支上的代码。
>>>>>>>之后的dev是该分支的名字。
对于简单的合并,手工编辑,然后去掉这些标记,最后像往常的提交一样先add再commit即可。
git merge 的参数
(1) --ff 或 无参数 : fast-forward 不推荐
注意没参数的情况下merge是fast-forward的,即Git将master分支的指针直接移到dev的最前方。换句话说,如果顺着一个分支走下去可以到达另一个分支的话,那么Git在合并两者时,只会简单移动指针,所以这种合并成为快进式(Fast-forward)。
(2) --no-ff : 实力推荐
使用 --no- ff参数后,会执行正常合并,在合并的分支上生成一个新节点。为了保证版本演进的清晰,希望采用这种做法。
(3) --squash 压合合并(squashed commits) :
将一条分支上的若干个提交条目压合成一个提交条目,提交到另一条分支的末梢。
把dev分支上的所有提交压合成主分支上的一个提交,即压合提交:
git checkout master
git merge --squash dev
此时,dev上的所有提交已经合并到当前工作区并暂存,但还没有作为一个提交,可以像其他提交一样,把这个改动提交到版本库中:
git commit –m “something from dev”
(4) --abort 等其他
--abort abort the current in-progress merge
推荐使用(2), (3)(4)是一些特殊情况和需求时才会用的。
恢复操作
git resetreset主要用来把3个树的内容恢复到指定的commit上(git log 查看 commit值)。
3个参数 --hard, --mixed, --soft
--hard 将3个树的内容都恢复到指定的commit上。对应下图的1,2,3 操作。
--mixed (默认,无参数时的默认值)将版本区(HEAD指针)和缓存区的内容恢复到指定的commit上。对应下图的1,2操作。
--soft 只是将版本区(HEAD指针)恢复到指定的commit上。对应下图的1操作。
参考图
git reset --mixed == git reset --soft + git reset HEAD
git reset --hard == git reset --mixed + git checkout -- filename
用HEAD可以替代commit值,
HEAD -- 当前,倒数第一次提交
HEAD^ -- 当前的当前,倒数第二次提交
HEAD^^ -- 倒数第三次提交
git checkout -- filename
注意 “--” 前后有空格,用缓存区的内容替换工作去的内容。相当于命令git add filename 的反射操作。
上面的reset都是以commit为单位进行的。
git reset 之后也可以加文件名, 表示针对那个文件的对应操作。
这里在介绍一下当commit不满意时的处理。
(1) -m 写的不好
git commit -amend
执行命令之后,就会推到编辑器模式下,可以编辑-m 的内容了。
然后会形成一个新的提交(commit值)。
(2) git reset --soft HEAD^
之后就用git commit来提交吧。
rebase操作
git rebase参考 http://blog.csdn.net/hudashi/article/details/7664631/
里面说的深入浅出,非常棒。
主要用于获取其他分支的修改。
比如, 你从master分支上checkout一个分支mywork进行开发。同时其他人也会从master分支checkout新分支进行开发。在你的分支merge到master分支之前,其他人的分支可能都merge到master分支上了,即master分支向前走了一步或几步。此时,如果你需要别人的修改,你可以
(1) 合并
$ git checkout master
$ git pull origin master
$ git checkout mywork
$ git merge master --no-ff
(2) rebase
果你想让"mywork"分支历史看起来像没有经过任何合并一样,你也许可以用 git rebase。
$ git checkout mywork
$ git rebase origin
原理:
这些命令会把你的"mywork"分支里的每个提交(commit)取消掉,并且把它们临时保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把"mywork"分支更新 为最新的"origin"分支,最后把保存的这些补丁应用到"mywork"分支上。
日志操作
git log 和git reflog
git reflog 可以查看所有分支的所有操作记录(包括(包括commit和reset的操作),包括已经被删除的commit记录,git log则不能察看已经删除了的commit记录。
本地篇的内容应该能满足大多数需求。