Git的简单使用

1,创建仓库

   建立仓库目录

mkdir rep

2,初始化仓库

  使用如下命令

git init

  初始化后会产生隐藏文件.git

  初始化成功之后配置一下自己的个人信息:

$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"

因为git是版本控制系统,每个账号要有自己的身份,每个机器都必须自报家门:你的名字和Email地址。你也许会担心,如果有人故意冒充别人怎么办?这个不必担心,首先我们相信大家都是善良无知的群众,其次,真的有冒充的也是有办法可查的。

注意git config命令的--global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址

使用如下命令查看配置信息:

git config -l

 

3,仓库添加文件

git add readme.txt

Unix的哲学是“没有消息就是好消息”,说明添加成功。

4,提交文件到仓库

git commit -m "first file"

命令格式和svn类似,SVN提交文件命令为:svn commit -m "first file"

5,修改文件提交文件,查看当前仓库状态

git status

结果如下

On branch master
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

no changes added to commit (use "git add" and/or "git commit -a")

看到文件状态为被更改

6,差分查看修改的内容

使用如下命令

git diff readme.txt

结果如下

diff --git a/readme.txt b/readme.txt
index 5bd6a90..3b62fc4 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,3 @@
 Git is a version control system.
 First time to modified!
+Second time to modified!

 

7,提交修改

和SVN不同的是提交前要先add然后再commit

8,查看提交记录

git log
commit d9334820e9f8746578868808d113fc6b8f3360f1
Author: xxxxxx <xxxxxx@163.com>
Date:   Tue Feb 7 23:49:56 2017 +0800

    Secmond time to modified

commit 97321e6d811c2c2dc2f2fce8e270676480af8b72
Author:  xxxxxx <xxxxxx@163.com>
Date:   Tue Feb 7 23:29:58 2017 +0800

    first time to modifed

commit 0fc77bb42c42482b355fed5960a5338c2db2ca25
Author:  xxxxxx <xxxxxx@163.com>
Date:   Tue Feb 7 23:19:42 2017 +0800

    first file

提交日志按时间降序排列

如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:

$ git log --pretty=oneline
d9334820e9f8746578868808d113fc6b8f3360f1 Secmond time to modified
97321e6d811c2c2dc2f2fce8e270676480af8b72 first time to modifed
0fc77bb42c42482b355fed5960a5338c2db2ca25 first file

需要注意的是前面一长串d9334820e9f8746578868808d113fc6b8f3360f1是版本号,这有别于SVN,SVN是连续的正整数。这是因为git是分布式的版本管理系统,每个仓库的版本号都不能重复。

9,回退版本

在git中用HEAD表示当前版本,也就是最新提交的d9334820e9f8746578868808d113fc6b8f3360f1版本,上一个版本就是HEAD^,上两个版本是HEAD^^,往前100个版本HEAD~100.

$ git reset --hard HEAD^

输出结果如下

$ git reset --hard HEAD^
HEAD is now at 97321e6 first time to modifed

查看日志如下

$  git log
commit 97321e6d811c2c2dc2f2fce8e270676480af8b72
Author: zealzhangz <tenderfacepalm@163.com>
Date:   Tue Feb 7 23:29:58 2017 +0800

    first time to modifed

commit 0fc77bb42c42482b355fed5960a5338c2db2ca25
Author: zealzhangz <tenderfacepalm@163.com>
Date:   Tue Feb 7 23:19:42 2017 +0800

    first file

如果还想回到之前最新的版本,需要知道版本号

git reset --hard d93348
git reset --hard d93348
HEAD is now at d933482 Secmond time to modified

然后又回到最新版本了,版本号d93348不一定要写全,但是要能唯一确定一个版本。

如果版本号已经不记得了,可以使用git reflog,git reflog用来记录你的每一次命令

$git reflog

结果如下

$ git reflog
d933482 HEAD@{0}: reset: moving to d93348
97321e6 HEAD@{1}: reset: moving to HEAD^
d933482 HEAD@{2}: commit: Secmond time to modified
97321e6 HEAD@{3}: commit: first time to modifed
0fc77bb HEAD@{4}: commit (initial): first file

这样就能查找到相关的版本号了。

盗张图:

详细可参考:http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013744142037508cf42e51debf49668810645e02887691000

10、工作区和暂存区

工作区:GIT存储文件的物理目录,比如我当前的/Documents/dev/p/rep目录。工作区有一个隐藏的.git目录,和svn类似,svn也有一个隐藏目录.svn。可以把.git称之为版本库目录(Respository Directory)里面存储了git的很多配置信息。最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

盗图如下:

 

回顾前面的提交文件到git分两步走:

第一步、git add ,实际上是把文件添加到暂存区。

第二部、git commit ,实际上是把内容提交到当前分支。我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。

因此我们可以分多次把文件提交到暂存区,然后一次性commit。

需要注意的是:commit只会提交本次暂存区里面的文件,没有add到暂存区的文件,在commit时是不会提交到分支的。

使用如下命令可以对比工作区和最新版本库的区别:

git diff HEAD -- readme.txt

11、撤销修改

  1)只在工作区进行了修改没有add

$ git status
On branch master
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

no changes added to commit (use "git add" and/or "git commit -a")

Git会告诉你,git checkout -- file可以丢弃工作区的修改

因此使用如下命令丢弃工作区的修改

$ git checkout -- readme.txt 
$ git status
On branch master
nothing to commit, working tree clean

注意:如果有多次修改,并且已经有几次add到暂存区,那么git checkout -- readme.txt 命令将会回到添加到暂存区后的状态,也就是执行命令后工作区修改的内容被丢弃了,并且和当前暂存区一致。git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令

  2)修改已经add到暂存区

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   readme.txt

Git同样告诉我们,用命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区:

git reset HEAD readme.txt 
Unstaged changes after reset:
M    readme.txt
$ git status
On branch master
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

no changes added to commit (use "git add" and/or "git commit -a")

  3)修改已经add且commit

  可以按照上面回退版本的方法进行回退,不过,这是有条件的,就是你还没有把自己的本地版本库推送到远程,因为Git是分布式版本控制系统。

12、删除文件

  使用如下两个命令

$git rm del.txt
$git commit -m "deleted file"  del.txt
$git rm del.txt 
rm 'del.txt'
$ ls
LICENSE    readme.txt
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    del.txt

13、远程仓库

git本地仓库与GitHub远程仓库协同工作

1)注册GitHub账号不走略过,在本地使用如下命令生成公钥并上传到GitHub

$ssh-keygen -t rsa -C "myemail@163.com"

一路回车后就生成好了公私钥文件在用户的根目录,注意目录是隐藏的。

$ ls
config      id_rsa      id_rsa.pub  known_hosts

拷贝公钥内容id_rsa.pub到GitHub

2)添加GitHub远程库并同步本地git库到GitHub

建好库之后我们根据提示选择推送本地已经有的库到刚建好的GitHub远程仓库。

把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。

$ git remote add origin https://github.com/xxxxx/learngit.git
$ git push -u origin master
Username for 'https://github.com': xxxxxx
Password for 'https://xxxxxx@github.com': 
Counting objects: 30, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (23/23), done.
Writing objects: 100% (30/30), 2.49 KiB | 0 bytes/s, done.
Total 30 (delta 8), reused 0 (delta 0)
remote: Resolving deltas: 100% (8/8), done.
To https://github.com/xxxxxxx/learngit.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。推送成功后,可以立刻在GitHub页面中看到远程库的内容已经和本地一模一样.

3)从远程仓库克隆

上一节讲的是如果先有了本地项目,如何同步到GitHub远程仓库。如果我们是一个新的项目,从零开始的项目,最好先在远程仓库上创建然后再克隆到本地工作。创建仓库参照上一步骤,创建好之后我们使用以下命令进行克隆。

$ git clone git@github.com:zealzhangz/clonerepository.git
Cloning into 'clonerepository'...
The authenticity of host 'github.com (192.30.253.113)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.253.113' (RSA) to the list of known hosts.
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.

GitHub给出的地址不止一个,还可以用https://github.com/michaelliao/gitskills.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https

14、创建与合并分支

分支的概念就不多讲了,原理和SVN分支的概念如出一辙。下面讲一下创建并且管理分支的一些命令:

  1)创建并切换分支

$ git checkout -b dev
Switched to a new branch 'dev'

git checkout 加上-b参数表示创建并切换分支,等同于以下两条命令:

$ git branch dev
$ git checkout dev

  2)查看当前分支

$ git branch
* dev
  master

git branch命令会列出所有分支,当前分支前面会标一个*号。

  3)切换分支

$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

4)合并分支

  把dev分支合并到master分支,首先切换到master分支,然后使用以下命令合并:

$ git merge dev
Updating 6a61034..17447bc
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)

注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。合并完成后,就可以放心地删除dev分支了:

$ git branch -d dev
Deleted branch dev (was 17447bc).

查看当前分支信息:

$ git branch
* master

  5)常用命令小结

    查看分支:git branch

    创建分支:git branch <name>

    切换分支:git checkout <name>

    创建+切换分支:git checkout -b <name>

    合并某分支到当前分支:git merge <name>

    删除分支:git branch -d <name>

15、解决冲突

使用上面的学习的命令git checkout -b feature1创建并切换分支到feature1分支,然后分支上更改文件并提交,切换到master分支,切换到master分支时会有如下提示:

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.

会提示feature1分支比master分支超前一个commit。

更改同一行,并提交,现在分支情况如下:

这种情况下git无法执行快速合并,只能试图把各自的修改合并起来,但是这种合并就会有冲突,比如两个分支更改了同一行。产生冲突如下:

$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.

查看状态如下:

$ git status
On branch master
Your branch is ahead of 'origin/master' by 3 commits.
  (use "git push" to publish your local commits)
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")

此时打开文件手动修复冲突:

  1 Git is a version control system.
  2 First time to modified!
  3 Second time to modified!
  4 Git is a free software
  5 Git has a mutable index called stage.
  6 Git tracks changes.
  7 acbcd
  8 switch brance
  9 <<<<<<< HEAD
 10 Creating a new branch iS quick AND simple.
 11 =======
 12 Creating a new branch IS quick AND simple.
 13 >>>>>>> feature1
以下表示当前版本的内容

9 <<<<<<< HEAD
 10 Creating a new branch iS quick AND simple.
 11 =======
以下表示feature1分支当前版本的内容
 11 =======
 12 Creating a new branch IS quick AND simple.
 13 >>>>>>> feature1

因此需要手动解决冲突如下
  1 Git is a version control system.
  2 First time to modified!
  3 Second time to modified!
  4 Git is a free software
  5 Git has a mutable index called stage.
  6 Git tracks changes.
  7 acbcd
  8 switch brance
  9 Creating a new branch is quick AND simple.

再次提交

$ git add readme.txt 
$ git commit -m "resolved conflict"
[master d1c25a1] resolved conflict

现在两个分支情况如下

 

使用git log -graph查看分支合并情况

git log --graph --pretty=oneline --abbrev-commit
*   d1c25a1 resolved conflict
|\  
| * 371a890 feature1 second commit
* | 8998da9 master second commit
|/  
* 03fef75 feature1
* 17447bc commit brance
* 6a61034 delete file
* d7d12ed 123
* 781f988 deleted file
* a30f515 delete test.txt
* 23702d1 add test.txt
* bb2a69a git tracks changes
* 53638b2 understand how stage works
* 4bbda7e changed
* d933482 Secmond time to modified
* 97321e6 first time to modifed
* 0fc77bb first file

最后删除feature1分支

$ git branch -d feature1
Deleted branch feature1 (was 371a890).

 

 16、分支管理策略

通常情况下合并分支时git会使用fast forward模式,这种模式下删除分支后会丢掉分支信息。如果禁用Fast forward模式git会在merge分支时生成一个新的commit,这样就可以保存分支的历史信息。

下面实战一下加上参数--no-ff方式的git merge。

1)首先建立并切换分支更改readme.txt文件并提交

$ git checkout -b dev
Switched to a new branch 'dev'

2)切换到master分支并加上--no-ff并merge到master分支

$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
 readme.txt | 1 +
 1 file changed, 1 insertion(+)
$ git log --graph --pretty=oneline --abbrev-commit
*   4d3f53d merge with no-ff
|\  
| * 950fa74 --no-ff git merge
|/  
*   d1c25a1 resolved conflict
|\  
| * 371a890 feature1 second commit
* | 8998da9 master second commit
|/  
* 03fef75 feature1
* 17447bc commit brance
* 6a61034 delete file
* d7d12ed 123
* 781f988 deleted file
* a30f515 delete test.txt
* 23702d1 add test.txt
* bb2a69a git tracks changes
* 53638b2 understand how stage works
* 4bbda7e changed
* d933482 Secmond time to modified
* 97321e6 first time to modifed
* 0fc77bb first file

不使用Fast forwar模式merge就如下图:

开发中管理分支的几个基本策略:

①master分支为稳定发布分支,也可以叫release分支,每次往生产环境发布的分支

②Dev分支为开发分支,每位开发者分别从Dev分支拉自己的开发分支,本地测试通过后提交到Dev分支,等待测试小组测试通过了merge到master分支发布。

③feature/bug分支,如果增加了新功能且改动较大做好重新拉一个分支,待开发结束后再合并到Dev分支、再合并到master分支,bug分支或者经紧急对应分支,每次生产报了一个阻塞用户或者比较紧急的bug可以单独拉一个分支对应。如果bug不紧急可以等到下次正常发布一起。

盗图如下:

 

17、保存现场stash功能

有这样一个场景,我正在开发新功能,开发到一半突然来个紧急bug要修。新功能一时半会开发不完,因此已经更改或新建的新功文件能不能和bug一起提交。这个时候就需要保留开发到一半的现场,等我修完bug再接着开发,因此git有stash(存储,储存的意思)功能来保留现场。实战如下:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
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

no changes added to commit (use "git add" and/or "git commit -a")
$ git stash
Saved working directory and index state WIP on master: 4d3f53d merge with no-ff
HEAD is now at 4d3f53d merge with no-ff
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean

可以看到执行git stash命令后查看工作区状态就是干净的.

现在要执行如下步骤修bug,完成后并回复工作区间

①切换到指定分支一般是当前的稳定分支(trunk)分支并拉出bug分支

②在bug分支issure-001修复bug后提交

③切换到trunk分支合并bug分支并发布

④好了之后可以删除bug分支切换到刚开始的Dev分支恢复之前的工作现场继续开发

注意:这里的工作区间可以恢复到任何分支,比如刚创建的分支,但可能会有冲突需要解决

恢复stash有两种方法:

法一:

使用git stash list查看当前的保存的工作区间列表,使用git stash apply stash@{0}来进行恢复,这种恢复方式,恢复之后之前保存的stash还是存在的,不会被删除。需要手动删除。

$ git stash list
$ git stash apply stash@{0}
$ git stash drop

法二:

git stash pop,恢复的同时把stash内容也删了

$ git stash pop

 

详细操作步骤如下:

$ git checkout master

$ git checkout -b issure-001
Switched to a new branch 'issure-001'
$ vim readme.txt 
$ git add readme.txt 
$ git commit -m "fix bug 001"
[issure-001 821f542] fix bug 001
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ git merge --no-ff -m "merged bug fix 001" issure-001
Merge made by the 'recursive' strategy.
 readme.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git stage list
fatal: pathspec 'list' did not match any files
$ git stash list
stash@{0}: WIP on master: 4d3f53d merge with no-ff
$ git branch -d issure-001
Deleted branch issure-001 (was 821f542).
$ git checkout -b dev
Switched to a new branch 'dev'
$ git stash list
stash@{0}: WIP on master: 4d3f53d merge with no-ff
$ git branch
* dev
  master
$ git stash apply stash@{0}
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
$ git stash list
stash@{0}: WIP on master: 4d3f53d merge with no-ff
$ git stash drop
Dropped refs/stash@{0} (417d5d4606fde5e2e92f9c7659e38d498caa6b63)
$ git status
On branch dev
Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

    both modified:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")

 

 

posted @ 2017-02-08 00:21  海阔天空990  阅读(482)  评论(0编辑  收藏  举报