Git 基本的工作流程总结
2015-09-30 18:43
453 查看
一、创建版本库
mkdir learngit
$ cd learngit
通过git init命令把这个目录变成Git可以管理的仓库
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/
二、修改文件,比较不同
1.git status命令可以让我们时刻掌握仓库当前的状态
2.git diff:git diff顾名思义就是查看difference,显示的格式正是Unix通用的diff格式
三、版本回退
1.本控制系统肯定有某个命令可以告诉我们历史记录,在Git中,我们用git log命令查看
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:
$ git log --pretty=oneline
3628164fb26d48395383f8f31179f24e0882e1e0 append GPL
ea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributed
cb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file
2.Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交3628164...882e1e0(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100
我们要把当前版本“append GPL”回退到上一个版本“add distributed”,就可以使用git reset命令:
$ git reset --hard HEAD^
HEAD is now at ea34578 add distributed
3.版本回退又前进(找ID号)Git提供了一个命令git reflog用来记录你的每一次命令
$ git reflog
ea34578 HEAD@{0}: reset: moving to HEAD^
3628164 HEAD@{1}: commit: append GPL
ea34578 HEAD@{2}: commit: add distributed
cb926e7 HEAD@{3}: commit (initial): wrote a readme file
4.HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id。
穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。
要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。
四、管理修改
五、撤销修改
1.git checkout -- file可以丢弃工作区的修改,git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令
2.命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:
一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
$ git checkout -- readme.txt
一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
总之,就是让这个文件回到最近一次git commit或git add时的状态,
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file。
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退,不过前提是没有推送到远程库。
六、删除文件
1.在Git中,删除也是一个修改操作,我们实战一下,先添加一个新文件test.txt到Git并且提交
$ git add test.txt
$ gitcommit -m"add test.txt"
[master94cdc44]add test.txt
1 file changed,1 insertion(+)
create mode100644 test.txt
一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了:
$rm test.txt
这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了:
$git status
no changes added to commit (use"git add"and/or"git commit -a")
现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit:
$ git rm test.txt
rm 'test.txt'
$ gitcommit -m"remove test.txt"
[master d17efd8] remove test.txt
1 file changed,1 deletion(-)
delete mode100644 test.txt
现在,文件就从版本库中被删除了。
另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
$git checkout -- test.txt
git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”
命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。
还有一种删除文件夹及其下所有的文件(dev):
git rm raindow -r -f
同步删除操作到远程分支
git commit -m "delete raindow"
提交分支:
git push origin master
Git删除空目录
使用git rm -rf dir 命令删除非空目录之后,本地还是会有空的目录存在,这时候空目录已经是untracked状态了。
解决办法是再删除掉untracked状态的目录,命令如下:git clean -fd
六、添加远程库
要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git,
eg:git remote add origin git@github.com:baitxaps/PlayDrama
关联后,使用命令git push -u origin master第一次推送master分支的所有内容;
此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;
分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,而SVN在没有联网的时候是拒绝干活的!当有网络的时候,再把本地提交推送一下就完成了同步,真是太方便了
七、从远程库克隆
要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。
git clone git@github.com:baitxaps/PlayDrama.git
Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快
https://github.com/baitxaps/PlayDrama.git 这样的地址
八、创建与合并分支
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
创建+切换分支:git checkout -b <name>
合并某分支到当前分支:git merge <name>
删除分支:git branch -d <name>
九、解决冲突
准备新的featureOne分支,继续我们的新分支开发
$git checkout -b featureOne
Switched to a new branch‘featureOne'
修改readme.txt最后一行,改为:
Creating a new branch is quick AND simple.
在featureOne分支上提交:
$ git add readme.txt
$ gitcommit -m"AND simple"
[feature175a857c]AND simple
1 file changed,1 insertion(+),1 deletion(-)
切换到master分支:
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by
1commit.
Git还会自动提示我们当前master分支比远程的master分支要超前1个提交。
在master分支上把readme.txt文件的最后一行改为:
Creating anew branch is quick & simple.
提交:
$git add readme.txt
$git commit -m"& simple"
[master400b400] & simple
1 file changed,1 insertion(+),1 deletion(-)
现在,master分支和feature1分支各自都分别有新的提交,变成了这样:
这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突,我们试试看:
$git merge feature1
Auto-merging readme.txt
CONFLICT (content):Merge conflictin readme.txt
Automatic merge failed; fix conflictsandthen commit the result.
果然冲突了!Git告诉我们,readme.txt文件存在冲突,必须手动解决冲突后再提交。git status也可以告诉我们冲突的文件:
$git status
# On branch master
# Your branch is ahead of 'origin/master' by
2 commits.
#
# Unmerged paths:
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: readme.txt
#
no changes added to commit (use"git add"and/or"git commit -a")
我们可以直接查看readme.txt的内容:
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<<HEAD
Creatinganewbranchisquick &simple.
=======
CreatinganewbranchisquickANDsimple.
>>>>>>> feature1
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们修改如下后保存:
Creating anew branch is quickand simple.
再提交:
$git add readme.txt
$git commit -m"conflict fixed"
[master59bc1cb] conflict fixed
现在,master分支和featureOne分支变成了下图所示:
用带参数的git log也可以看到分支的合并情况:
$ git log --graph --pretty=oneline --abbrev-commit
* 59bc1cb conflict fixed
|\
| *75a857cAND simple
* |400b400 & simple
|/
* fec145a branch test
...
最后,删除featureOne分支:
$git branch -d feature1
Deleted branch feature1 (was75a857c).
工作完成。
十、分支管理策略
通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
下面我们实战一下--no-ff方式的git merge:
首先,仍然创建并切换dev分支:
$git checkout -b dev
Switched to a new branch'dev'
修改readme.txt文件,并提交一个新的commit:
$ git add readme.txt
$ gitcommit -m"add merge"
[dev6224937]add merge
1 file changed,1 insertion(+)
现在,我们切换回master:
$git checkout master
Switched to branch'master'
准备合并dev分支,请注意--no-ff参数,表示禁用Fast forward:
$git merge --no-ff -m"merge with no-ff" dev
Merge made by the'recursive' strategy.
readme.txt | 1 +
1 file changed,1 insertion(+)
因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。
合并后,我们用git log看看分支历史:
$ git log --graph --pretty=oneline --abbrev-commit
* 7825a50 mergewith no-ff
|\
| *6224937 add merge
|/
* 59bc1cb conflict fixed
...
可以看到,不使用Fast forward模式,merge后就像这样:
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
Git分支十分强大,在团队开发中应该充分应用。
合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。
十、Bug分支
软件开发中,bug就像家常便饭一样。有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支issue-101来修复它,但是,等等,当前正在dev上进行的工作还没有提交:
$git status
# On branch dev
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: hello.py
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: readme.txt
#
并不是你不想提交,而是工作只进行到一半,还没法提交,预计完成还需1天时间。但是,必须在两个小时内修复该bug,怎么办?
幸好,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
$git stash
Saved working directoryand index stateWIP on dev:6224937 add merge
HEAD is now at6224937 add merge
现在,用git status查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug。
首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建临时分支:
$git checkout master
Switched to branch'master'
Your branch is ahead of'origin/master' by6 commits.
$git checkout -b issue-101
Switched to a new branch'issue-101'
现在修复bug,需要把“Git is free software ...”改为“Git is a free software
...”,然后提交:
$git add readme.txt
$git commit -m"fix bug 101"
[issue-101 cc17032] fix bug101
1 file changed,1 insertion(+),1 deletion(-)
修复完成后,切换到master分支,并完成合并,最后删除issue-101分支:
$git checkout master
Switched to branch'master'
Your branch is ahead of'origin/master' by2 commits.
$git merge --no-ff -m"merged bug fix 101" issue-101
Merge made by the'recursive' strategy.
readme.txt | 2 +-
1 file changed,1 insertion(+),1 deletion(-)
$git branch -d issue-101
Deleted branch issue-101 (was cc17032).
太棒了,原计划两个小时的bug修复只花了5分钟!现在,是时候接着回到dev分支干活了!
$git checkout dev
Switched to branch'dev'
$git status
# On branch dev
nothing to commit (working directory clean)
工作区是干净的,刚才的工作现场存到哪去了?用git stash list命令看看:
$git stash list
stash@{0}:WIP ondev:6224937 add merge
工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:
一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
另一种方式是用git stash pop,恢复的同时把stash内容也删了:
$git stash pop
# On branch dev
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: hello.py
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: readme.txt
#
Dropped refs/stash@{0} (f624f8e5f082f2df2bed8a4e09c12fd2943bdd40)
再用git stash list查看,就看不到任何stash内容了:
$git stash list
你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:
$ git stash apply stash@{0}
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。
十一、Feature分支
软件开发中,总有无穷无尽的新的功能要不断添加进来。
添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。现在,你终于接到了一个新任务:开发代号为Vulcan的新功能,该功能计划用于下一代星际飞船。
$ git checkout -b feature-vulcan
Switched to a new branch
'feature-vulcan'
开发完毕:
$ git add vulcan.py
$ git commit -m "add feature vulcan"
[feature-vulcan 756d4af] add feature vulcan
1 file changed, 2 insertions(+)
create mode 100644 vulcan.py
切回dev,准备合并:
$git checkout dev
一切顺利的话,feature分支和bug分支是类似的,合并,然后删除。
但是,
就在此时,接到上级命令,因经费不足,新功能必须取消!
虽然白干了,但是这个分支还是必须就地销毁:
$git branch -d feature-vulcan
error:The branch'feature-vulcan' isnot fully merged.
If you are sure you want to delete it, run'git branch -D feature-vulcan'.
销毁失败。Git友情提醒,feature-vulcan分支还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用命令git branch -D feature-vulcan。
现在我们强行删除:
$ git branch -D feature-vulcan
Deleted branch feature-vulcan (was 756d4af).
开发一个新feature,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。
十二、多人协作
首先,可以试图用git push origin branch-name推送自己的修改;
如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
如果合并有冲突,则解决冲突,并在本地提交;
没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!
如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git
branch --set-upstream branch-name origin/branch-name。
这就是多人协作的工作模式
多人协作总结;
多人协作查看远程库信息,使用git remote -v;
本地新建的分支如果不推送到远程,对其他人就是不可见的;
从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name;
从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。
PS:
git 常用命令:
1.本地分支与远程分支关联
//git checkout master-test(本地) origin/master-test(远程)
git checkout -b master-test origin/master-test
2.git提交代码到远程分支
git push origin BRANCH #BRANCH是你远程分支的名字
3.如果你只是要恢复一个文件,如"hello.rb", 你就要使用 git $ git checkout -- hello.rb
http://gitbook.liuhui998.com/4_9.html
$ git reflog
ea34578 HEAD@{0}: reset: moving to HEAD^
3628164 HEAD@{1}: commit: append GPL
ea34578 HEAD@{2}: commit: add distributed
cb926e7 HEAD@{3}: commit (initial): wrote a readme file
4.HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id。
穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。
要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本
5、git提交代码到远程分支
git push origin BRANCH #BRANCH是你远程分支的名字
6、切换分支
http://blog.csdn.net/xqs83/article/details/7382074
git branch –r
7、创建远程分支
http://www.gitguys.com/topics/adding-and-removing-remote-branches/?lang=zh
创建一个新的分支到远程目录中可以使用这种方法,先将分支添加到你的本地仓库,然后将该本地分支推送到远程仓库中. 让我们看看我们现在有哪些分支:
amy$ git branch
* master
我们只有一个分支. 还没多到数不清的地步. 因此Amy创建了一个新的分支 v0:
amy$ git branch v0
然后她将分支 v0 推送到远程仓库 origin.
git push的语法为: git push [remote-repository-name] [branch-or-commit-name]:
amy$ git push origin v0
8、git branch --set-upstream master-v4.1.3 origin/master-v4.1.3
git clone --recursive https://github.com/Cocoanetics/DTCoreText.git Externals/DTCoreText
相关文章推荐
- findFocus-获得拥有焦点的控件
- IOS开发 ShareExtension
- 高效解决 Tomcat PermGen Space 问题
- 小试List View
- JS生成随机的由字母数字组合的字符串
- 《Java并发编程实战》第十二章 测试并发程序 读书笔记
- HTML调用CSS的四种方法
- IntelliJ IDEA 项目相关的几个重要概念介绍
- PDF在线阅读 FlexPaper 惰性加载 ;
- 第三次作业-------结对编程
- 动画切换rootViewController
- 20那天android得知
- 黑马程序员——C语言基础---通讯录
- expected specifier-qualifier-list before 'size_t'
- Android性能专项测试之TraceView工具(Device Monitor)
- Js自定义属性
- Search in Rotated Sorted Array
- 【容斥原理】HDOJ GCD 1695
- DL Code Editor user manual
- 使用ViewPager和FragmentPagerAdapter实现Tab