柴少鹏的官方网站 技术在分享中进步,水平在学习中升华

git的常用操作(三)

http://www.51niux.com/?id=148  这里已经搭建好gitlab服务器了,这里就直接操作向这个服务器来提交。

注:这里的二、三部分命令顺序是借鉴着廖雪峰老师的博客:https://www.liaoxuefeng.com/ 的git教程写的,可以直接飞去这里了解,我这里 就是做个操作命令记录,方便日后查阅。

一、git的常用操作

1.1、创建版本库并提交

$ git --version   #查看一下git的版本
git version 2.13.1.windows.2
$ git config --global user.name "wangshuai"  #告诉git当前的用户名

$ git config --global user.email "wangshuai@51niux.com"  #告诉git当前的邮件地址
$ mkdir demo  #demo就是创建的git库的根目录,又称工作区。
$ cd demo/
$ git init  #初始化版本库,此目录下隐藏的.git目录就是Git版本库(又叫仓库,repository)
$ echo "Hello" >> test.txt  #创建一个文件

$ git add test.txt  #将这个新文件添加到版本库,但是一般使用git add . 或者git add *,这样多文件多目录就都添加到版本库了。

$ git commit -m "one commit"  #将此次添加代码仓库。-m后面是提交说明

$ git log  #可以查看提交日志,结果里面commit后面会跟着一个很长的字符串ID版本号,我们就取前7位就可以了,就可以实现版本回滚等操作

$ git log --stat  #可以查看每次提交的文件变更统计

$ git reflog #记录所有操作的版本号

1.2 git的状态查看

$ git status  #可以查看当前状态
$ git rev-parse --git-dir  #显示版本库.git所在的位置

$ git rev-parse --show-toplevel  #显示工作区的根目录

$ git rev-parse --show-cdup   #显示从当前目录退回到根目录的深度

1.3 git中的版本库,暂存区和工作区

图片.png

图中左侧为工作区,右侧为版本库。在版本库中标记为index的区域为暂存区,标记为master的是master分支所代表的目录树。

工作区(Working Directory):就是你在电脑里能看到的目录,比如我们上面创建的demo目录。

版本库(Repository):工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
objects 标识的区域为 Git 的对象库,实际位于.git/objects目录下。
暂存区跟踪记录了工作区的文件名和文件状态(修改时间,文件大小等信息)。
图中的HEAD是一个指向最新commit的引用,可以通过版本回退的方式改变HEAD的指向。
执行git add会更新暂存区(stage)的目录树,同时将工作区的文件内容生成一个对象放入objects对象库中,在暂存区记录了该对象的索引index。
执行git commit会更新版本库的目录树,commit成功后版本库指向的目录树就是暂存区的目录树。因为我们创建Git版本库时,Git自动为我们创建了唯一的一个master分支,所以,现在,git commit就是往master分支上提交更改。

简单的说就是add式将修改的东西从工作区放到stoge(暂存区),commit将提交更改,实际上就是把暂存区的所有内容提交到当前分支,所以add之后修改的东西,commit是不会提交的,只是将暂存区的内容提交。

1.4 暂存区和目录树的命令查看或操作

$ git ls-tree -l HEAD    #使用了git底层命令ls-tree来查看,-l显示文件的大小。HEAD(版本库中当前提交)指向的目录树。

100644 blob 417cacb35ecdfb24555b61fedd922726568bc305      12    test.txt
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391       0    test2.txt
040000 tree c25f00bc9034941236fdabe8cf411fd0918e437e       -    testdir

#第一列字段(前两个是文件,第三个是个目录),后面是文件的权限文件权限是644。

#第二列字段前两个说明是blob对象(文件),而tree说明是目录

#第三列字段则是该文件在对象库中对应的ID(40位的SHA1哈希值格式的ID)。

#第四列字段是文件的大小。

#第五列字段是文件名或者目录名。

$ git ls-files -s  #显示暂存区的目录树

$ git diff   #工作区和暂存区的比较

$ git diff --cached  #暂存区和HEAD的比较
$ git diff HEAD    #工作区和HEAD的比较

$ git diff HEAD -- test.txt  #可以单独查看某个文件的区别

$ git checkout -- test2.txt   #这里就是撤销test2.txt文件add之后的所有操作,也就是让这个文件回到最近一次git commit或git add时的状态,如果不加-- 就变成切换到某个分支了。

$ git reset HEAD test2.tx  #如果test2.txt只是将修改add到了暂存区,可以通过这个命令将修改从暂存区放回到工作区。

$ git rm 文件名  #多个文件名 空格隔开,这个才是删除git里面文件的正确步骤然后再commit,用rm只是工作区的文件没有了,暂存区里面还是有的。

博文来自:www.51niux.com

1.5 版本回退

$ git log   #git log命令显示从最近到最远的提交日志,我们可以看到3次提交,都有Date时间显示的

commit 0835649c3ecdca9741dbbc579544d2f869507593 (HEAD -> master)
Author: wangshuai <wangshuai@51niux.com>
Date:   Sun Jul 23 16:09:06 2017 +0800

    commit update three

commit 3e0584436c5b518321abde7f8a4f7bc36ad8da9b   #这里是commit id号,而我们只需要取前7位
Author: wangshuai <wangshuai@51niux.com>
Date:   Sun Jul 23 15:34:55 2017 +0800

    commit update agin

commit 479585abfe042229c996796c74db6568d60a04a0
Author: wangshuai <wangshuai@51niux.com>
Date:   Sat Jul 22 23:48:19 2017 +0800

    one commit

$ git log --pretty=oneline  #可以只显示commit id号,输出简化一点,然后从上到下,最上面是最近一次改动,以此类推

$ git reset --hard HEAD^  #HEAD表示当前版本,上一个版本是HEAD^(或者直接指定id号如3e05844 ),上上版本就是HEAD^^,再多就指定commit id号吧。

图片.png

$ git log --pretty=oneline  #再查看一下,最新的版本已经发生了变化

图片.png

#现在如果又想变回原来的哪个版本,但是你现在用git log已经找不到哪个版本号了,你又没有记录之前的版本号是什么。

$ git reflog  #reflog记录git的每一次命令

图片.png

$ git reset --hard 0835649  #就又倒退回去了,就是让HEAD指针指定版本号,一般都是指定当前的版本号

1.6 和远端的版本库连接

首先登陆我们创建的gitlab:192.168.1.121,创建一个demo版本库:git@192.168.1.121:wanghai/demo.git

然后因为我们已经操作很多了,所以不能用git clone的形式的,正好用另外一种形式

$ git remote add origin git@192.168.1.121:wanghai/demo.git  #添加远程仓库,origin就代表了后面的链接

$ git remote -v  #可以查看一下,如果没有推送权限,就看不到push的地址。或者通过$ cat .git/config看一下  #git remote rm origin 这是删除远程的git仓库

$ git add .
$ git commit
$ git push -u origin master  #把当前的master分支提交给origin,其实就是提交到origin后面所代表的远程url。由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

图片.png

#从上图中可以看出,已经将本地创建的一些东西推送到远端的仓库里面去了。

#再有修改啥的,因为现在是我们自己一个人玩,设计不到合并什么的东西,直接$ git push origin master就可以了,不用再去合并分支什么的了。

1.7 Git fetch和git pull的区别

Git中从远程的分支获取最新的版本到本地有这样2个命令:
 git fetch:

相当于是从远程获取最新版本到本地,不会自动merge

git fetch origin master    #首先从远程的origin的master主分支下载最新的版本到origin/master分支上
git log -p master..origin/master   #比较本地的master分支和origin/master分支的差别
git merge origin/master            #最后进行合并

当然也可以用下面的这种写法:

git fetch origin master:tmp
git diff tmp 
git merge tmp

git pull:

相当于是从远程获取最新版本并merge到本地

git pull origin master  #其实相当于git fetch 和 git merge

在实际使用中,git fetch更安全一些,因为在merge前,我们可以查看更新情况,然后再决定是否合并

博文来自:www.51niux.com

二、分支管理

2.1 创建分支与合并

$ git checkout -b dev  #创建dev分支,然后切换到dev分支,-b 参数表示创建并切换,相当于下面两条命令:

$ git branch dev
$ git checkout dev

#我们在创建dev分支,一个新的指针指向了dev,如果切换到dev分支,HEAD就指向了这个指针。

$ git branch  #查看当前的分支
图片.png

#从图中可以看到列出了所有的分支,当前分支是dev分支,当前分支前面会有一个*

$ vim test2.txt  #编辑此文件新加一行“creating a new dev ranch”

$ git add test2.txt
$ git commit -m "dev branch test"
$ git checkout master  #切换回master分支

$ cat test2.txt  #再查看一下,发现没有新加的那句话

$ git merge dev  #git merge命令用于合并指定的分支到当前的分支

图片.png

#注意标红的地方,这是“快进模式”的合并.也就是直接把master指向dev的当前提交,所以合并速度非常快。

$ git branch -d dev  #可以选择删除dev分支,下次再要改东西的时候再创建一个dev分支再去写完测试没问题了再合并到master分支上。

注(如果你dev分支commit了,但是还没有合并,这时候要删除dev分支):

$ git branch -d dev
图片.png

#如上图所示,是删除不了这个分支的,上图中也有提示

$ git branch -D dev  #就强制删除了这个dev分支了。

2.2 解决合并时候的冲突

git的分支很强大,分支开发难免合并的时候遇到冲突的时候,记得13年接触git,那时候不是我管理,是一个开发来管理这套系统就经常解决冲突问题。

下面用一个小例子来演示一下分支冲突:

$ git checkout -b dev  #创建并切换到dev

$ vim test  #写一句话

$ git add test.txt
$ git commit -m "dev commit"
$ git checkout master
图片.png

#上图是Git还提示我们当前master分支比远程的master分支要超前1个提交。

$ vim test.txt  #在master分支上也有test.txt添加一句话

$ git add test.txt
$ git commit -m "master commit"
现在,master分支和dev分支各自都分别有新的提交,变成了这样:

图片.png
$ git merge dev  #将dev合并到当前的分支master。

图片.png

#这种情况下,Git无法执行“快速合并”,但这种合并就可能会有冲突只能试图把各自的修改合并起来。上面是告诉我们test.txt有冲突。

$ git status  #也可以看到冲突的状态,会有一些详细的提示

$ cat test.txt   #查看下文件可以直接看到冲突的地方

图片.png

#Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们可以根据冲突的内容的上下位置也可以看到,====上面是master的内容,也就是当前分支的内容,下面是dev分支的内容,而且它下面还有>>>>>>>dev标记呢。

$ cat test.txt  #那就手工的去修改一下文件的内容,将master添加的内容去掉。

图片.png

$ git add test.txt
$ git commit -m "commit dev and master"  #再提交
$ git merge dev  #再合并会提示你已经是最新的了不用合并了

图片.png

现在,master分支和dev分支变成了下图所示:

图片.png
$ git log --graph --pretty=oneline --abbrev-commit  #可以查看分支的合并情况,git log --graph可以查看分支合并图图片.png
注:合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。如:$ git merge --no-ff -m "merge with no-ff" dev  #--no-ff参数,表示禁用Fast forward,通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息

当然gitlab上面也可以查看:

图片.png

#注意上面那条红线的每个红点,鼠标放在上面可以看到每次commit的ID。

2.3 需要解决bug的时候

如果你正改着内容呢,在dev分支上,现在有个master的bug需要你处理,master应该是稳定版的,不应该在master上面进行修改,你应该保证本地工作区是干净的没有任何修改,不然你就算创建了分支,也会把dev分支上面未修改的东西给带过来,就算提交也会把dev上面未写完的东西提交。

解决上面的问题有两种方法:

第一种方法:

$ vim test.txt  #比如现在又在test.txt里面写了一句话,但是我们还么写完不想提交呢

$ git status  #会提示你工作区并不是clean状态,有文件更改了
$ git stash   #将更改未提交的内容放到一个临时区域
$ git checkout master  #切换回master分支

$ git checkout -b bug-101 #创建一个bug-101分支并切换到此分支上

$ vim test2.txt  #如test2.txt就是要解决Bug的文件,现在改完了
$ git add test2.txt
$ git commit -m "fix bug 101"
$ git checkout master
$ git merge --no-ff -m "merged bug fix 101" bug-101

$  git push -u origin master  #bug解决了也提交了
$ git checkout dev   #切换回dev分支继续解决自己没解决的问题吧
$ git stash list  #可能有多个分支,都存了临时区域,就不止会有一条,看看刚才放到临时区域的修改内容在哪个位置
图片.png

$ git stash apply stash@{0}   #这就是指定来恢复,当然$ git stash apply 是恢复最近保存的临时工作状态,也就是恢复stash@{0}

$ git stash drop stash@{0}  #当然你都恢复了,就不想临时工作区再保存着了,就通过这个命令来删除,当然$ git stash drop是删除找到的第一个。

$ git stash pop stash@{0}  #是上面两条命令的结合,既恢复了临时保存的修改,又将临时工作区里面的记录删除掉。

第二种方法:

就是把修改的先commit提交一下了。

注:

dev分支一般是开发分支,一般不会像我操作这样老是删除掉的,master分支是最稳定的分支一般不会老是去跟它合并的,都是其他的开发人员自己的分支跟dev分支合并,然后测试没有问题了,再让dev分支去跟master分支合并。

$ git push origin dev   #push后面跟着prigin远程库地址,然后最后指定分支,就是将哪个分支也推送到远程主机仓库。

图片.png

博文来自:www.51niux.com

三、标签管理

打标签发布代码,是代码上线上面一个很长说的一个口头禅。你看github上面也有很多tags告诉你版本号。

3.1 创建标签

$ git checkout master

$ git tag v1.0   #给当前打一个v1.0的标签

$ git log --pretty=oneline --abbrev-commit  #如果以前有的commit忘记打标签了,先将历史查出来

图片.png

$ git tag v0.9 5a1ae90  #指定commit的id号来打标签

$ git tag  #查看标签,标签不是按时间顺序列出,而是按字母排序的。

图片.png

$ git tag -a v0.8 -m "version 0.8 released" a17c2f7 #可以对标签做注释

$ git show v0.8  #可以查看标签的具体信息

图片.png
3.2 操作标签

$ git tag -d v0.8  #删除标签,如果创建的标签都只存储在本地,没有推送到远程,可以在本地安全删除(一般是新打的标签)。

$ git push origin v1.0  #推送某个标签到远程
图片.png

$ git push origin --tags #可以把本地的标签一次性的全推送远程。

如果打的标签已经推送到了远程,就要执行下面的操作:

$ git tag -d v0.9 #现在本地删除标签

$ git push origin :refs/tags/v0.9  #从远程删除标签

图片.png

注(忽略特殊文件):

忽略特殊文件.gitignone
在根目录下创建一个$ vim .gitignore  文件
#在过滤文件生效之前的文件,以后也不会生效,只有当前过滤设置之后的新文件,才有效。

作者:忙碌的柴少 分类:git使用 浏览:1870 评论:0
留言列表
发表评论
来宾的头像