
本文共 13585 字,大约阅读时间需要 45 分钟。
一.分支
1.分支的简介
在进行提交操作时,Git 会保存一个提交对象(commit object),
2.分支的创建
创建一个 testing 分支, 你需要使用 git branch
命令:
$ git branch testing
3.分支的切换
$ git checkout testing
再提交一次:
$ vim test.rb$ git commit -a -m 'made a change'
首先,我们创建dev
分支,然后切换到dev
分支:
$ git checkout -b devSwitched to a new branch 'dev'
git checkout
命令加上-b
参数表示创建并切换,相当于以下两条命令:
$ git branch dev$ git checkout devSwitched to branch 'dev'
用git branch
命令查看当前分支:
$ git branch* dev master
git branch
命令会列出所有分支,当前分支前面会标一个*
号。
对readme.txt做个修改,加上一行:
Creating a new branch is quick.
4.分支的删除
使用带 -d
选项的 git branch
命令来删除分支:
$ git branch -d hotfixDeleted branch hotfix (3a0874c).
5.分支的合并
检出到你想合并入的分支,然后运行 git merge
命令:
$ git checkout masterSwitched to branch 'master'$ git merge iss53Merge made by the 'recursive' strategy.index.html |
1 +1 file changed, 1 insertion(+)
遇到冲突时的分支合并
有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。 如果你对 #53 问题的修改和有关 hotfix
的修改都涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突:
$ git merge iss53Auto-merging index.htmlCONFLICT (content): Merge conflict in index.htmlAutomatic merge failed; fix conflicts and then commit the result.
此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status
命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件:
$ git statusOn branch masterYou have unmerged paths. (fix conflicts and run "git commit")Unmerged paths: (use "git add..." to mark resolution)
both modified:
index.htmlno changes added to commit (use "git add" and/or "git commit -a")
任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。 出现冲突的文件会包含一些特殊区段,看起来像下面这个样子:
<<<<<<< HEAD:index.htmlcontact : email.support@github.com=======please contact us at support@github.com>>>>>>> iss53:index.html
这表示 HEAD
所指示的版本(也就是你的 master
分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(=======
的上半部分),而 iss53
分支所指示的版本在 =======
的下半部分。 为了解决冲突,你必须选择使用由 =======
分割的两部分中的一个,或者你也可以自行合并这些内容。 例如,你可以通过把这段内容换成下面的样子来解决冲突:
please contact us at email.support@github.com
上述的冲突解决方案仅保留了其中一个分支的修改,并且 <<<<<<<
, =======
, 和 >>>>>>>
这些行被完全删除了。 在你解决了所有文件里的冲突之后,对每个文件使用 git add
命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。
6.分支管理
$ git branch iss53* master testing
master
分支前的 *
字符:它代表现在检出的那一个分支
Bug分支
有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
Git还提供了一个stash
功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
$ git stashSaved working directory and index state WIP on dev: f52c633 add merge
首先确定要在哪个分支上修复bug,假定需要在master
分支上修复,就从master
创建临时分支:
$ git checkout masterSwitched to branch 'master'Your branch is ahead of 'origin/master' by 6 commits. (use "git push" to publish your local commits)
$ git checkout -b issue-101Switched 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 4c805e2] fix bug 101 1 file changed, 1 insertion(+), 1 deletion(-)
修复完成后,切换到master
分支,并完成合并,最后删除issue-101
分支:
$ git checkout masterSwitched to branch 'master'Your branch is ahead of 'origin/master' by 6 commits. (use "git push" to publish your local commits)$ git merge --no-ff -m "merged bug fix 101" issue-101Merge made by the 'recursive' strategy. readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
现在,是时候接着回到dev
分支
$ git checkout devSwitched to branch 'dev'$ git statusOn branch devnothing to commit, working tree clean
工作区是干净的,刚才的工作现场存到哪去了?用git stash list
命令看看:
$ git stash liststash@{0}: WIP on dev: f52c633 add merge
工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:
一是用git stash apply
恢复,但是恢复后,stash内容并不删除,你需要用git stash drop
来删除;
另一种方式是用git stash pop
,恢复的同时把stash内容也删了:
$ git stash popOn branch devChanges to be committed: (use "git reset HEAD..." to unstage)
new file: hello.pyChanges not staged for commit: (use "git add..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory)
modified: readme.txtDropped refs/stash@{0} (5d677e2ee266f39ea296182fb2354265b91b3b2a)
再用git stash list
查看,就看不到任何stash内容了:
$ git stash list
你可以多次stash,恢复的时候,先用git stash list
查看,然后恢复指定的stash,用命令:
$ git stash apply stash@{0}
7.dev 分支
准备开发:
$ git checkout -b dev-vulcanSwitched to a new branch 'dev-vulcan'
5分钟后,开发完毕:
$ git add vulcan.py$ git statusOn branch dev-vulcanChanges to be committed: (use "git reset HEAD..." to unstage)
new file: vulcan.py$ git commit -m "add feature vulcan"[feature-vulcan 287773e] add feature vulcan 1 file changed, 2 insertions(+) create mode 100644 vulcan.py
切回dev
,准备合并:
$ git checkout dev
销毁
$ git branch -d dev-vulcanerror: The branch 'dev-vulcan' is not fully merged.If you are sure you want to delete it, run 'git branch -D dev-vulcan'.
销毁失败。Git友情提醒,dev-vulcan
分支还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用大写的-D
参数。
$ git branch -D dev-vulcanDeleted branch dev-vulcan (was 287773e).
参考:
二.多人协作
克隆仓库的命令格式是git clone [url]
$ git clone https://github.com/libgit2/libgit2
自定义本地仓库的名字,你可以使用如下命令:
$ git clone https://github.com/libgit2/libgit2 mylibgit
发生冲突时:先pull,在本地合并,然后才能push成功。合并后,分支变成了下面:
$ git log --graph --pretty=oneline --abbrev-commit* d1be385 (HEAD -> master, origin/master) init hello* e5e69f1 Merge branch 'dev'|\ | * 57c53ab (origin/dev, dev) fix env conflict| |\ | | * 7a5e5dd add env| * | 7bd91f1 add new env| |/ * | 12a631b merged bug fix 101|\ \ | * | 4c805e2 fix bug 101|/ / * | e1e9c68 merge with no-ff|\ \ | |/ | * f52c633 add merge|/ * cf810e4 conflict fixed
Git有一种称为rebase的操作,有人把它翻译成“变基”
在和远程分支同步后,我们对hello.py
这个文件做了两次提交。用git log
命令看看:
$ git log --graph --pretty=oneline --abbrev-commit* 582d922 (HEAD -> master) add author* 8875536 add comment* d1be385 (origin/master) init hello* e5e69f1 Merge branch 'dev'|\ | * 57c53ab (origin/dev, dev) fix env conflict| |\ | | * 7a5e5dd add env| * | 7bd91f1 add new env...
推送本地分支:
$ git push origin masterTo github.com:michaelliao/learngit.git ! [rejected]
master -> master (fetch first)error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'hint: Updates were rejected because the remote contains work that you dohint: not have locally. This is usually caused by another repository pushinghint: to the same ref. You may want to first integrate the remote changeshint: (e.g., 'git pull ...') before pushing again.hint: See the 'Note about fast-forwards' in 'git push --help' for details.
这样就失败了,这说明有人先于我们推送了远程分支。按照经验,先pull一下:
$ git pullremote: Counting objects: 3, done.remote: Compressing objects: 100% (1/1), done.remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0Unpacking objects: 100% (3/3), done.From github.com:michaelliao/learngit d1be385..f005ed4 master
-> origin/master * [new tag]
v1.0
-> v1.0Auto-merging hello.pyMerge made by the 'recursive' strategy. hello.py | 1 + 1 file changed, 1 insertion(+)
再用git status
看看状态:
$ git statusOn branch masterYour branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits)nothing to commit, working tree clean
用git log
看看:
$ git log --graph --pretty=oneline --abbrev-commit* e0ea545 (HEAD -> master) Merge branch 'master' of github.com:michaelliao/learngit|\ | * f005ed4 (origin/master) set exit=1* | 582d922 add author* | 8875536 add comment|/ * d1be385 init hello...
现在把本地分支push到远程,有没有问题?有,不好看
输入命令git rebase
试试:
$ git rebaseFirst, rewinding head to replay your work on top of it...Applying: add commentUsing index info to reconstruct a base tree...M
hello.pyFalling back to patching base and 3-way merge...Auto-merging hello.pyApplying: add authorUsing index info to reconstruct a base tree...M
hello.pyFalling back to patching base and 3-way merge...Auto-merging hello.py
再用git log
看看:
$ git log --graph --pretty=oneline --abbrev-commit* 7e61ed4 (HEAD -> master) add author* 3611cfe add comment* f005ed4 (origin/master) set exit=1* d1be385 init hello...
最后,通过push操作把本地分支推送到远程:
Mac:~/learngit michael$ git push origin masterCounting objects: 6, done.Delta compression using up to 4 threads.Compressing objects: 100% (5/5), done.Writing objects: 100% (6/6), 576 bytes | 576.00 KiB/s, done.Total 6 (delta 2), reused 0 (delta 0)remote: Resolving deltas: 100% (2/2), completed with 1 local object.To github.com:michaelliao/learngit.git f005ed4..7e61ed4 master -> master
再用git log
看看效果:
$ git log --graph --pretty=oneline --abbrev-commit* 7e61ed4 (HEAD -> master, origin/master) add author* 3611cfe add comment* f005ed4 set exit=1* d1be385 init hello...
远程分支
1.推送
$ git push origin serverfixCounting objects: 24, done.Delta compression using up to 8 threads.Compressing objects: 100% (15/15), done.Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.Total 24 (delta 2), reused 0 (delta 0)To https://github.com/schacon/simplegit * [new branch]
serverfix -> serverfix
抓取数据时
$ git fetch originremote: Counting objects: 7, done.remote: Compressing objects: 100% (2/2), done.remote: Total 3 (delta 0), reused 3 (delta 0)Unpacking objects: 100% (3/3), done.From https://github.com/schacon/simplegit * [new branch]
serverfix
-> origin/serverfix
如果想要在自己的 serverfix
分支上工作,可以将其建立在远程跟踪分支之上:
$ git checkout -b serverfix origin/serverfixBranch serverfix set up to track remote branch serverfix from origin.Switched to a new branch 'serverfix'
2.跟踪分支
$ git checkout --track origin/serverfixBranch serverfix set up to track remote branch serverfix from origin.Switched to a new branch 'serverfix'
如果想要将本地分支与远程分支设置为不同名字,你可以轻松地增加一个不同名字的本地分支的上一个命令:
$ git checkout -b sf origin/serverfixBranch sf set up to track remote branch serverfix from origin.Switched to a new branch 'sf'
设置已有的本地分支跟踪一个刚刚拉取下来的远程分支,或者想要修改正在跟踪的上游分支,你可以在任意时间使用 -u
或 --set-upstream-to
选项运行 git branch
来显式地设置。
$ git branch -u origin/serverfixBranch serverfix set up to track remote branch serverfix from origin.
如果想要查看设置的所有跟踪分支,可以使用 git branch
的 -vv
选项
$ git branch -vv iss53
7e424c3 [origin/iss53: ahead 2] forgot the brackets master
1ae2a45 [origin/master] deploying index fix* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it testing 5ea463a trying something new
3.删除远程分支
$ git push origin --delete serverfixTo https://github.com/schacon/simplegit - [deleted]
serverfix
参考:
三.忽略特殊文件
1.忽略特殊文件的原则:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的
.class
文件; - 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
有些时候,你想添加一个文件到Git,但发现添加不了,原因是这个文件被.gitignore
忽略了:
$ git add App.classThe following paths are ignored by one of your .gitignore files:App.classUse -f if you really want to add them.
确实想添加该文件,可以用-f
强制添加到Git:
$ git add -f App.class
可以用git check-ignore
命令检查:
$ git check-ignore -v App.class.gitignore:3:*.class
App.class
.gitignore
的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。
忽略某些文件时,需要编写.gitignore
;
.gitignore
文件本身要放到版本库里,并且可以对.gitignore
做版本管理!
四.标签的管理
1.列出标签
$ git tagv0.1v1.3
如果只对 1.8.5 系列感兴趣,可以运行:
$ git tag -l 'v1.8.5*'v1.8.5v1.8.5-rc0v1.8.5-rc1v1.8.5-rc2v1.8.5-rc3v1.8.5.1v1.8.5.2v1.8.5.3v1.8.5.4v1.8.5.5
2.创建标签
轻量标签(lightweight)与附注标签(annotated)
2.1 附注标签 附注标签是存储在 Git 数据库中的一个完整对象
$ git tag -a v1.4 -m 'my version 1.4'$ git tagv0.1v1.3v1.4
-m
选项指定了一条将会存储在标签中的信息
通过使用 git show
命令可以看到标签信息与对应的提交信息:
$ git show v1.4tag v1.4Tagger: Ben StraubDate: Sat May 3 20:19:12 2014 -0700my version 1.4commit ca82a6dff817ec66f44342007202690a93763949Author: Scott Chacon Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
2.2 轻量标签 轻量标签本质上是将提交校验和存储到一个文件中 - 没有保存任何其他信息
$ git tag v1.4-lw$ git tagv0.1v1.3v1.4v1.4-lwv1.5
如果在标签上运行 git show
,你不会看到额外的标签信息。 命令只会显示出提交信息:
$ git show v1.4-lwcommit ca82a6dff817ec66f44342007202690a93763949Author: Scott ChaconDate: Mon Mar 17 21:52:11 2008 -0700
changed the version number
3.后期打标签
$ git log --pretty=oneline15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support0d52aaab4479697da7686c15f77a3d64d9165190 one more thing6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function4682c3261057305bdd616e23b64b0857d832627b added a todo file166ae0c4d3f420721acbb115cc33848dfcc2121a started write support9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme
假设在 v1.2 时你忘记给项目打标签,也就是在 “updated rakefile” 提交。 你可以在之后补上标签。 要在那个提交上打标签,你需要在命令的末尾指定提交的校验和(或部分校验和):
$ git tag -a v1.2 9fceb02
4.共享标签
$ git push origin v1.5Counting objects: 14, done.Delta compression using up to 8 threads.Compressing objects: 100% (12/12), done.Writing objects: 100% (14/14), 2.05 KiB | 0 bytes/s, done.Total 14 (delta 3), reused 0 (delta 0)To git@github.com:schacon/simplegit.git * [new tag]
v1.5 -> v1.5
如果想要一次性推送很多标签,也可以使用带有 --tags
选项的 git push
命令
$ git push origin --tagsCounting objects: 1, done.Writing objects: 100% (1/1), 160 bytes | 0 bytes/s, done.Total 1 (delta 0), reused 0 (delta 0)To git@github.com:schacon/simplegit.git * [new tag]
v1.4 -> v1.4 * [new tag]
v1.4-lw -> v1.4-lw
5.删除标签
要删除掉你本地仓库上的标签,可以使用命令 git tag -d <tagname>
可以使用下面的命令删除掉一个轻量级标签:
$ git tag -d v1.4-lwDeleted tag 'v1.4-lw' (was e7d5add)
应该注意的是上述命令并不会从任何远程仓库中移除这个标签,你必须使用 git push <remote> :refs/tags/<tagname>
来更新你的远程仓库:
$ git push origin :refs/tags/v1.4-lwTo /git@github.com:schacon/simplegit.git - [deleted]
v1.4-lw
6. 检出标签
如果你想查看某个标签所指向的文件版本,可以使用 git checkout
命令
参考:
转载地址:https://www.cnblogs.com/chenxi67/p/10433056.html 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
关于作者
