基本概念
工作区:工作区就是我们项目的代码所在文件夹,除了.git
部分
暂存区:我们提交代码在add
的时候都是添加到暂存区
仓库(repository):仓库分本地仓库跟远程仓库,本地仓库就是.git
里面的,远程仓库就是托管与github
等第三方平台,或者远程git
服务器上的仓库
基本操作
我比较常用的是在第三方平台上创建repository
然后clone
代码到本地,例如
git clone https://github.com/zhujp/slim-api.git
这样在本地就会有个slim-api
目录,也就是我们工作区所在位置。
发布版本
一般git那边的是开发(dev)版本,我们如果需要发布稳定的版本
git tag 1.0
git push origin --tags
提交
比如我们新增或者修改了README.md
,需要提交到github
git add README.md #添加到暂存区
git commit -m '修改了README.md' # 提交到本地仓库
git pull # 从远程仓库更新代码
git push # 提交到远程仓库
状态
在提交代码到远程仓库之前,我们可以执行git status
,查看工作区的版本控制状态.
新增了一个文件vilay.txt
,之后,执行命令 git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
vilay.txt
nothing added to commit but untracked files present (use "git add" to track)
我们提交到暂存区(git add vilay.txt
),然后执行git status
查看,
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: vilay.txt
有新增文件,我们提交到本地仓库去,git commit vilay.txt -m 'add vilay.txt'
,再看下状态git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
这下就提示我们,可以提交到远程仓库了.我们每一步操作都可以用命令git status
来查看工作区状态,可以根据提示然后进行后面的操作.
冲突
在没有任何意外的情况下这样就ok了。但是在协程开发的时候,你同事也修改了README.md
,并且提交了,这样就会发生了冲突。示例:
Auto-merging test.txt
CONFLICT (add/add): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
文件示例:
<<<<<<< HEAD
hello test
=======
hello world
>>>>>>> 17a4308990036fda9a5372ff686356464a5ba6ab
冲突解决办法:修改冲突的文件,把冲突提示的代码删了,修改之后如下
hello test
hello world
然后重新执行上面的提交步骤
git add test.txt
git commit -m 'update test.txt'
git push
版本回退
既然是版本控制器,我要恢复到之前版本怎么办?
git reset –hard HEAD^ # 回退到上一个版本
git reset –hard HEAD^^ # 回退到上上个版本
要是1000个版本呢,1000个^ ?这肯定不科学
git reset –hard HEAD~1000 # 回退到前1000个版本
那我想回退到某一个版本,但是不知道是第几个版本怎么办?根据版本号回退,语法如下
git reset --hard 版本号
用命令git log
查看版本号,结果像这样
commit 75051a7c2abf3041fe99f0f266de764b65501447
Author: vilay <xxx@qq.com>
Date: Thu Jul 27 20:26:05 2017 +0800
test.txt
commit 17a4308990036fda9a5372ff686356464a5ba6ab
Merge: bbcb6b3 72a9cfd
Author: vilay <xxx@qq.com>
Date: Thu Jul 27 20:24:42 2017 +0800
commit
后面的就是版本号了,如果版本过多,用q
退出查看日志。
版本号有了,恢复到指定版本就指日可待了
git reset --hard 17a4308990036fda9a5372ff686356464a5ba6ab # 回退到指定版本号
删除文件
删除文件有两个思路
第一个思路
rm test.txt
然后查看状态
git status
显示:
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: test.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
deploy.php
no changes added to commit (use "git add" and/or "git commit -a")
根据提示这个时候,我们可以做两个操作,
第一,把删除文件状态提交到暂存区,也就是
git add test.txt
或者把文件暂存区状态删除
git rm test.txt
第二,因为只是物理上本地删除,还可以从版本库中恢复
git checkout -- test.txt
我们回到之前刚执行删除命令rm test.txt
,步骤,继续说删除文件
git add test.txt
git commit -m 'delete test.txt'
也可以使用下面命令
git rm test.txt
git commit -m 'delete test.txt'
结果显示
[master 57ca3a0] delete test.txt
1 file changed, 2 deletions(-)
delete mode 100644 test.txt
删除成功。
rm
,git rm
的区别
rm:使用rm删除了文件之后(rm test.txt
),需要把删除状态提交到暂存区(git add .text.txt
),然后提交(git commit -m 'delete test.txt'
),或者直接用命令提交git commit -am 'delete test.txt'
git rm:使用git rm 删除文件(git rm test.txt
),已经把缓存去状态更改,直接提交即可 (git commit -m 'delete test.txt'
)
分支
分支概念理解:所谓分支就是类似于两个独立的项目,完全不影响,比如在开发项目的时候,你开发一个模块,另一个同事开发另一个模块,代码还没写完如果提交上去可能会导致应用程序崩了,但是有了分支概念,你每次提交都是提交在你的分支上,没有进行合并处理是不会影响到主分支的.这样的好处是,你可以对你的不完善代码也进行版本控制管理,还不用担心影响到线上项目.
我们创建个开发分支(dev)
创建并切换到分支
git checkout -b dev
结果:
$ git checkout -b dev
Switched to a new branch 'dev'
查看所有分支
git branch
结果显示:
$ git branch
* dev
master
前面带(*)号的就是当前分支
切换到主分支(master)
git checkout master
现在功能开发完了,我想把dev开发分支的代码合并到主分支
首先进入,master
分支
git checkout master
合并
git merge dev
如果分支过多,肯定也会导致管理混乱的,所以一旦没用的分支我们可以删除处理
git branch -d dev
分支合并策略:git 默认合并是按照Fast forward
模式处理的,这种模式下,如果删除了分支,分支的任何信息都会丢失.哪天追溯的时候都不知道这边是经过合并的.git 有提供另一种方式合并,使用--no-ff
方式处理.
使用示例
git merge --no-ff -m "merge dev" dev
我们用git log看下日志
$ git log
commit 15fe494a13b370be09e5bdf9be48ed0b410dd57c
Merge: a26a6b1 a1aeed7
Author: vilay <zhujp1211@163.com>
Date: Fri Jul 28 12:50:23 2017 +0800
merge dev
这边就有分支合并信息了
git的分支这么强大,所以我们可以每个bug都可以创建一个分支,然后修复完合并到主分支去,在将bug修复分支删除了
场景:
你这下在开发分支(dev)上进行功能开发,突然接到反馈程序出bug了,需要马上修复,但是因为在dev分支上的工作并没有做完,不想提交
这下你就可以使用git
的 stash
功能了,命令git stash
$ git stash
Saved working directory and index state WIP on test: 15fe494 merge dev
HEAD is now at 15fe494 merge dev
git stash
会把当前的工作区现场保存起来,然后进入其它分支修改bug,修改完成回来之后可以通过命令查看保存的现场记录,命令git stash list
$ git stash list
stash@{0}: WIP on test: 15fe494 merge dev
然后恢复工作区,恢复有两种方式
第一种:使用git stash apply
,这种方式不会把stash删除,需要再执行命令git stash drop
,命令使用(git stash apply stash@{0}
)
第二种:使用git stash pop
分支使用策略:
我们在开发的时候可以主分支(master
)作为最稳定的版本分支,线上发布使用,平常开发不能再上面码代码,在开发的时候,引出一个开发分支(dev
),每个团队成员开发的时候,都新建自己的开发分支(例如:vilay
),功能开发完成之后,合并到dev分支,确定发布了,再把dev
分支合并到master
分支.
新功能分支
在开发新功能的时候,我们可以引出一个feature1
分支,功能开发完成之后,进入到dev分支,进行合并处理,如果因为其它因素,feature1
分支被取消,必须把分支删除,直接使用之前的删除命令会提示
git branch -d feature1
提示:
error: The branch 'feature1' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature1'.
分支未合并,不能删除,如果要删除只能强制删除,使用命令git branch -D feature1
Bug分支
每个bug都可以去创建个分支,但是有个地方我们要注意,确定在哪个分支上修复bug,就从哪个分支创建bug分支,例如master分支出现bug,就在master上创建bug分支
,这样避免在合并的时候引出其它的问题.
其它
本地仓库关联远程仓库
比如我们在本地执行了初始化仓库操作,示例
mkdir project
cd project
git init
这样在本地就生成了本地仓库。提交操作跟前面一样,但是我们如果哪天在远程也创建了仓库,想要关联起来。
首先,执行
git remote add origin https://github.com/zhujp/slim-api.git
然后,把本地分支(master)提交到远程分支(origin)去
git push -u origin master
我提交的时候报错了
To https://git.oschina.net/vilay/test.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/zhujp/slim-api.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
根据提示,执行
git pull
还是报错
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=origin/<branch> master
看提示应该是有两种解决方案,我这边是按第一种,增加个参数,第二种方案是把本地分支直接绑定到远程分支
git pull origin master --allow-unrelated-histories
执行成功了,完美。
完善的流程:
git init
git add .
git commit -m "first commit"
git remote add origin https://github.com/zhujp/slim-api.git
git push -u origin master
我们在使用clone的时候,git会自动把远程仓库的master与本地的master绑定在一起,远程仓库默认名称是origin
,我们可以用命令git remote
查看
$ git remote
origin
还有git remote -v
,查看我们从远程仓库抓取和推送的地址,没有push权限就看不到push地址
$ git remote -v
origin https://github.com/zhujp/slim-api.git (fetch)
origin https://github.com/zhujp/slim-api.git (push)
默认使用命令
git push = git push origin master
如果要推送其它的分支
git push origin dev
这样就会把本地的dev分支,push到远程仓库的dev分支.
在push到远程的dev分支之前,我们肯定要创建远程仓库的dev分支到本地的
git checkout -b dev origin/dev
如果在git pull过程中有报错 no tracking information
,说明本地分支与远程分支没有绑定
git branch --set-upstream-to=origin/<branch> master #进行绑定处理就可以了
分支是否需要推送到远程呢?
master
,跟dev
分支肯定是要的,master
作为主分支肯定要同步,dev
分支协作开发也是要的,bug
分支可能就不需要了,改完直接合并删除,feature
的话,协作开发就推送,独立开发就不用了.
git cherry-pick
如果不想全部提交的时候,使用命令部分提交
学习笔记,有误的地方,欢迎指正