美文网首页
Git学习笔记

Git学习笔记

作者: jadegg | 来源:发表于2017-06-14 12:27 被阅读0次

    [TOC]

    初始仓库(git init)

    $ git init 
    

    把文件添加到仓库(git add)

    $ git add 文件名 #单个文件
    或
    $ git add 文件名  文件名 文件名 #多个文件
    或
    $ git add . #全部文件 *也是一样
    

    把文件提交到仓库(git commit)

    $ git commit -m "本次提交的说明"
    

    查看仓库状态

    查看仓库当前状态(git status)

    $ git status
    

    查看仓库具体状态(git diff具体修改了什么内容)

    $ git diff #全部
    $ git diff 文件名 #单个文件的状态
    

    查看历史记录(git log/reflog)

    $ git log #不能察看已经删除了的commit记录
    $ git reflog #查看所有分支的所有操作记录
    

    当前版本(HEAD)

    HEAD #表示当前版本
    HEAD^ #表示上个版本
    HEAD^^ #表示上上一个版本
    HEAD~100 #表示往上100个版本
    

    版本回滚(git reset)

    $ git reset --hard HEAD^ #回退到上一个版本
    '或'
    $ git reset --hard 3628164 #指定回到某个版本3628164是commit id
    

    删除文件(git rm)

    $ git rm 文件名
    $ git commit -m "删除说明"
    

    本地仓库与远程库关联(git remote add)

     $ git remote add origin git@github.com:michaelliao/learngit.git
     #michaelliao表示GitHub账户名,远程库的名字就是origin
    

    本地库的内容推送到远程(git push)

     $ git push -u origin master #我们第一次推送master分支时,加上了-u参数
    $ git push origin master #其他时候不用加-u
    

    从远程库克隆(git clone)

    $ git clone git@github.com:michaelliao/gitskills.git
    

    分支管理(branch)

    创建+切换分支

    $ git checkout -b dev #首先,我们创建dev分支,然后切换到dev分支
    

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

    $ git branch dev #创建dev分支
    $ git checkout dev #切换到dev分支
    

    查看当前分支

    $ git branch #git branch命令会列出所有分支
    * dev
      master
      #当前分支前面会标一个*号
    

    切换分支(git checkout)

    $ git checkout master #切换回master分支
    

    合并某分支到当前分支(git merge)

    1. 通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
    $ git merge dev #我们把dev分支的工作成果合并到master分支上(git merge命令用于合并指定分支到当前分支)
    

    2.如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

    下面我们实战一下--no-ff方式的git merge

    $ git merge --no-ff -m "merge with no-ff" dev
    

    因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。

    合并后,我们用git log看看分支历史:

    $ git log --graph --pretty=oneline --abbrev-commit
    *   7825a50 merge with no-ff
    |\
    | * 6224937 add merge
    |/
    *   59bc1cb conflict fixed
    ...
    

    小结

    Git分支十分强大,在团队开发中应该充分应用。
    合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

    查看分支合并图(git log --graph)

    $ git log --graph --pretty=oneline --abbrev-commit
     # --pretty=oneline:一行显示,只显示哈希值和提交说明
     #--abbrev-commit:仅显示SHA-1的前几个字符,而非所有的40个字符
    
    分支合并图

    删除分支(git branch -d)

    $ git branch -d dev #合并完成后,就可以放心地删除dev分支了
    

    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
    #
    

    把当前工作现场“储藏”起来(git stash)

    并不是你不想提交,而是工作只进行到一半,还没法提交,预计完成还需1天时间。但是,必须在两个小时内修复该bug,怎么办?
    幸好,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:

    $ git stash
    

    查看“储藏”的工作现场(git stash list)

    $ git stash list
    

    恢复工作现场

    工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:

    一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;

    另一种方式是用git stash pop,恢复的同时把stash内容也删了:

    $ git stash pop
    

    视频

    小结

    来至

    修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;

    当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。

    Feature(功能)分支

    软件开发中,总有无穷无尽的新的功能要不断添加进来。

    添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。

    强行删除

    $ git branch -D feature-vulcan
    
    • 小结

    开发一个新feature,最好新建一个分支;

    如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。

    标签管理(tag)

    发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。

    Git的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(跟分支很像对不对?但是分支可以移动,标签不能移动),所以,创建和删除标签都是瞬间完成的。

    Git有commit,为什么还要引入tag?

    “请把上周一的那个版本打包发布,commit号是6a5819e...”

    “一串乱七八糟的数字不好找!”

    如果换一个办法:

    “请把上周一的那个版本打包发布,版本号是v1.2”

    “好的,按照tag v1.2查找commit就行!”

    所以,tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。

    创建标签(git tag <name>)

    $ git tag v1.0
    

    默认标签是打在最新提交的commit上的。有时候,如果忘了打标签,比如,现在已经是周五了,但应该在周一打的标签没有打,怎么办?

    方法是找到历史提交的commit id,然后打上就可以了:

    $ git log --pretty=oneline --abbrev-commit
    6a5819e merged bug fix 101
    cc17032 fix bug 101
    7825a50 merge with no-ff
    6224937 add merge
    59bc1cb conflict fixed
    400b400 & simple
    75a857c AND simple
    fec145a branch test
    d17efd8 remove test.txt
    ...
    

    比方说要对add merge这次提交打标签,它对应的commit id是6224937,敲入命令:

    $ git tag v0.9 6224937
    

    创建带有说明的标签(用-a指定标签名,-m指定说明文字)

    $ git tag -a v0.1 -m "version 0.1 released" 3628164
    

    查看标签(git tag)

    $ git tag #查看所以标签
    

    查看标签信息(git show <tagname>)

    $ git show v0.9
    commit 622493706ab447b6bb37e4e2a2f276a20fed2ab4
    Author: Michael Liao <askxuefeng@gmail.com>
    Date:   Thu Aug 22 11:22:08 2013 +0800
    
        add merge
    ...
    

    小结

    命令git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id;

    git tag -a <tagname> -m "blablabla..."可以指定标签信息;

    git tag -s <tagname> -m "blablabla..."可以用PGP签名标签;

    命令git tag可以查看所有标签。

    操作标签

    删除标签(git tag -d <tagname>)

    $ git tag -d v0.1
    Deleted tag 'v0.1' (was e078af9)
    

    推送标签到远程(git push origin <tagname>)

    $ git push origin v1.0
    Total 0 (delta 0), reused 0 (delta 0)
    To git@github.com:michaelliao/learngit.git
     * [new tag]         v1.0 -> v1.0
    

    或者,一次性推送全部尚未推送到远程的本地标签:

    $ git push origin --tags
    Counting objects: 1, done.
    Writing objects: 100% (1/1), 554 bytes, done.
    Total 1 (delta 0), reused 0 (delta 0)
    To git@github.com:michaelliao/learngit.git
     * [new tag]         v0.2 -> v0.2
     * [new tag]         v0.9 -> v0.9
    

    删除远程标签

    1. 先从本地删除
    $ git tag -d v0.9
    Deleted tag 'v0.9' (was 6224937)
    
    1. 然后,从远程删除。删除命令也是push,但是格式如下:
    $ git push origin :refs/tags/v0.9
    To git@github.com:michaelliao/learngit.git
     - [deleted]         v0.9
    

    小结

    命令git push origin <tagname>可以推送一个本地标签;

    命令git push origin --tags可以推送全部未推送过的本地标签;

    命令git tag -d <tagname>可以删除一个本地标签;

    命令git push origin :refs/tags/<tagname>可以删除一个远程标签。

    搭建Git服务器

    搭建Git服务器需要准备一台运行Linux的机器,强烈推荐用Ubuntu或Debian,这样,通过几条简单的apt命令就可以完成安装。

    假设你已经有sudo权限的用户账号,下面,正式开始安装。

    第一步,安装git:

    $ sudo apt-get install git
    

    第二步,创建一个git用户,用来运行git服务

    $ sudo adduser git
    

    第三步,创建证书登录:

    收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。

    第四步,初始化Git仓库:

    先选定一个目录作为Git仓库,假定是/srv/sample.git,在/srv目录下输入命令:

    $ sudo git init --bare sample.git
    

    Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git结尾。然后,把owner改为git:

    $ sudo chown -R git:git sample.git
    

    第五步,禁用shell登录:

    出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd文件完成。找到类似下面的一行:

    git:x:1001:1001:,,,:/home/git:/bin/bash
    

    改为:

    git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
    

    这样,git用户可以正常通过ssh使用git,但无法登录shell,因为我们为git用户指定的git-shell每次一登录就自动退出。

    第六步,克隆远程仓库:

    现在,可以通过git clone命令克隆远程仓库了,在各自的电脑上运行:

    $ git clone git@server:/srv/sample.git
    Cloning into 'sample'...
    warning: You appear to have cloned an empty repository.
    

    剩下的推送就简单了。

    管理公钥

    如果团队很小,把每个人的公钥收集起来放到服务器的/home/git/.ssh/authorized_keys文件里就是可行的。如果团队有几百号人,就没法这么玩了,这时,可以用Gitosis来管理公钥。

    管理权限

    有很多不但视源代码如生命,而且视员工为窃贼的公司,会在版本控制系统里设置一套完善的权限控制,每个人是否有读写权限会精确到每个分支甚至每个目录下。因为Git是为Linux源代码托管而开发的,所以Git也继承了开源社区的精神,不支持权限控制。不过,因为Git支持钩子(hook),所以,可以在服务器端编写一系列脚本来控制提交等操作,达到权限控制的目的。Gitolite就是这个工具。

    小结

    搭建Git服务器非常简单,通常10分钟即可完成;

    要方便管理公钥,用Gitosis;

    要像SVN那样变态地控制权限,用Gitolite。

    相关文章

      网友评论

          本文标题:Git学习笔记

          本文链接:https://www.haomeiwen.com/subject/hupsqxtx.html