美文网首页Git
git简要学习

git简要学习

作者: 奇而思 | 来源:发表于2018-06-12 19:26 被阅读3次

    1.0 Git基础

    Git 更像是把数据看作是对小型文件系统的一组快照。 每次你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。 为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个快照流。如下图所示

    Git快照流
    Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。SHA-1 散列(hash,哈希),这是一个由 40 个十六进制字符(0-9 和 a-f)组成字符串

    三种状态

    文件在git中有3种状态,已提交(committed),已修改(modified),已暂存(staged),对应了git中的三个工作区域概念:
    git仓库,工作区域,暂存区域。见图:

    git工作区域划分
    Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。

    工作目录是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。

    暂存区域是一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库目录中。 有时候也被称作“索引”,不过一般说法还是叫暂存区域。

    基本的 Git 工作流程如下:

    1.在工作目录中修改文件。

    2.暂存文件,将文件的快照放入暂存区域。

    3.提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。

    忽略文件

    在master目录下编辑.gitignore文件可以添加需要忽略的文件,.gitignore文件规范为:

    • 所有空行或者以 开头的行都会被 Git 忽略。

    • 可以使用标准的 glob 模式匹配。

    • 匹配模式可以以(/)开头防止递归。

    • 匹配模式可以以(/)结尾指定目录。

    • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。

    所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 使用两个星号(*) 表示匹配任意中间目录,比如a/**/z 可以匹配 a/z, a/b/za/b/c/z等。
    例子:

    # no .a files
    *.a
    
    # but do track lib.a, even though you're ignoring .a files above
    !lib.a
    
    # only ignore the TODO file in the current directory, not subdir/TODO
    /TODO
    
    # ignore all files in the build/ directory
    build/
    
    # ignore doc/notes.txt, but not doc/server/arch.txt
    doc/*.txt
    
    # ignore all .pdf files in the doc/ directory
    doc/**/*.pdf</pre>
    

    git diff

    • git diff --color-words 或者 git diff --word-diff 可以显示具体哪些词发生了变化。
    • git diff : Changes in the working tree not yet staged for the next commit. 显示还没有staged的部分的变化。add 之后就放入stage了。
    • git diff --cached: Changes between the index and your last commit; what you would be committing if you run "git commit" without "-a" option. staged的部分与上次commit之间的差异。如果运行git commit会提交这部分。
    • git diff HEAD: Changes in the working tree since your last commit; what you would be committing if you run "git commit -a" . 当前工作路径下与上次COMMIT的差异,如果运行git commit -a会提交这些更改。

    git add

    git add 执行之后会对修改过的文件照一个快照(snapshot), 然后把内容stage,并建立索引,以便commit的时候提交。

    git commit

    • git commit -a: 相当于git add; git commit -m

    移除文件 git rm

    git rm 命令已跟踪文件清单中移除并连带从工作目录中删除指定的文件。
    如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删还没有添加到快照的数据,这样的数据不能被 Git 恢复。

    另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加 .gitignore文件,不小心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一做法尤其有用。 为达到这一目的,使用 --cached 选项:
    移除暂存区文件:
    git rm --cached README

    git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式。 比方说:

    git rm log/\*.log

    **注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。
    **

    移动文件

    命令git mv file_from file_to相当于以下三条命令:

    mv file_from file_to
    git rm file_from
    git add file_to
    

    有时候用其他工具批处理改名的话,要记得在提交前删除老的文件名,再添加新的文件名。

    git log

    • git log : 查看各次commit的信息,最新的在最上面。
    • git log --oneline 可以查看简化版本,在一行内显示
    • git log --stat 列出了详细的信息。
    • git log --patch|-p更为详细的信息,还可以添加-2参数以获得最近2个commit的对比。
    • git log --graph 以图形形式显示
    • git log --pretty,后面可以跟oneline,format(后跟指定格式),例如:
      git log --pretty=oneline, git log --pretty=format:"%h %s"
    选项 说明
    %H 提交对象(commit)的完整哈希字串
    %h 提交对象的简短哈希字串
    %T 树对象(tree)的完整哈希字串
    %t 树对象的简短哈希字串
    %P 父对象(parent)的完整哈希字串
    %p 父对象的简短哈希字串
    %an 作者(author)的名字
    %ae 作者的电子邮件地址
    %ad 作者修订日期(可以用 --date= 选项定制格式)
    %ar 作者修订日期,按多久以前的方式显示
    %cn 提交者(committer)的名字
    %ce 提交者的电子邮件地址
    %cd 提交日期
    %cr 提交日期,按多久以前的方式显示
    %s 提交说明

    可以接受的格式为:

    选项 说明
    %H 提交对象(commit)的完整哈希字串
    %h 提交对象的简短哈希字串
    %T 树对象(tree)的完整哈希字串
    %t 树对象的简短哈希字串
    %P 父对象(parent)的完整哈希字串
    %p 父对象的简短哈希字串
    %an 作者(author)的名字
    %ae 作者的电子邮件地址
    %ad 作者修订日期(可以用 --date= 选项定制格式)
    %ar 作者修订日期,按多久以前的方式显示
    %cn 提交者(committer)的名字
    %ce 提交者的电子邮件地址
    %cd 提交日期
    %cr 提交日期,按多久以前的方式显示
    %s 提交说明

    当format与graph命令结合时很有用
    git log --pretty=format:"%h %s" --graph

    撤销操作

    重新提交

    有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有 --amend 选项的提交命令尝试重新提交:例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:

    git commit -m 'initial commit'
    $ git add forgotten_file
    $ git commit --amend
    

    最终你只会有一个提交 - 第二次提交将代替第一次提交的结果

    取消暂存的文件

    例如,你已经修改了两个文件并且想要将它们作为两次独立的修改提交,但是却意外地输入了 git add * 暂存了它们两个。 如何只取消暂存两个中的一个呢?
    git reset HEAD filename

    远程仓库使用

    git remote -v 显示远程仓库列表
    git fetch [remote-name] 将远程仓库内容拉取到本地,它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。
    git pull [remote-name] 将远程仓库内容拉取到本地,并进行合并到当前分支。
    git push [remote-name] [branch-name] 将分支推送到远程
    只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先将他们的工作拉取下来并将其合并进你的工作后才能推送。
    git remote show [remote-name] 会显示远程的更多信息,同样会列出远程仓库的 URL 与跟踪分支的信息。

    打标签

    使用打标签的方式来记录重要的发布节点
    git tag 列出标签
    git使用两种标签,轻量(lightweight)标签和附注(annotated)标签,推荐使用annotated标签,信息比较多。
    git tag -a v1.54 -m "my version v1.54" 打annotated标签
    git shown v1.54 显示tag的信息

    后期打标签

    git tag -a v1.2 9fceb02 只需要后面跟部分校验码就可以了。

    共享标签

    git push命令不会将标签传送到远程,可以使用下面的命令显示推送某个标签
    git push [remote-name] [tag-name]
    如果要推送多个标签,使用:
    git push [remote-name] --tags

    别名

    git config --global alias.unstage 'reset HEAD --'
    git config --global alias.last 'log -1 HEAD'
    可以看出,Git 只是简单地将别名替换为对应的命令。 然而,你可能想要执行外部命令,而不是一个 Git 子命令。 如果是那样的话,可以在命令前面加入 ! 符号。 如果你自己要写一些与 Git 仓库协作的工具的话,那会很有用。

    分支

    暂存操作会为每一个文件计算校验和(使用我们在 起步 中提到的 SHA-1 哈希算法),然后会把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 对象来保存它们),最终将校验和加入到暂存区域等待提交。
    当使用 git commit 进行提交操作时,Git 会先计算每一个子目录(本例中只有项目根目录)的校验和,然后在 Git 仓库中这些校验和保存为树对象。随后,Git 便会创建一个提交对象,它除了包含上面提到的那些信息外,还包含指向这个树对象(项目根目录)的指针。如此一来,Git 就可以在需要的时候重现此次保存的快照。
    看图

    image
    在一次提交后,包含3类文件,提交对象commit,目录的树对象tree,文件的blob对象。tree和blob是git对当前文件状态的一次快照snapshot。因此,每次提交产生的commit指向了一次snapshot。
    在多次提交后,后来提交的commit对象会指向上一次提交的父对象。分支就是一个指针,指向某次提交,另外git中还有一个默认的指针,HEAD,指向当前分支。关系如下:
    image
    当使用 git checkout bname后,HEAD指针就指向bname了。

    分支切换会改变你工作目录中的文件

    在切换分支时,一定要注意你工作目录里的文件会被改变。 如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。 如果 Git 不能干净利落地完成这个任务,它将禁止切换分支。
    git log --oneline --decorate --graph --all输出你的提交历史、各个分支的指向以及项目的分支分叉情况。

    git branch

    • git branch bname: 创建分支bname
    • git branch 列出所有分支,星号表示当前所在分支
    • git checkout bname: 切换到bname分支
    • git merge bname : 将bname合并到当前分支(可能是主分支)。如果存在矛盾(conflict),git会提示。使用git diff可以看到,编辑矛盾的文件(矛盾的地方会标记出来),然后git commit -a即可完成merge.
    • gitk,可以以图形形式查看
    • git branch -d bname: 删除bname分支。

    远程分支

    远程跟踪分支是远程分支状态的引用。 它们是你不能移动的本地引用,当你做任何网络通信操作时,它们会自动移动。 远程跟踪分支像是你上次连接到远程仓库时,那些分支所处状态的书签。
    它们以 (remote)/(branch) 形式命名。,本地无法修改,一般在进行网络操作时自动修改。
    像下图这样

    image
    本地的master和远程的master分支不同,如果要将本地master推送到远程是不行的,需要首先进行合并:
    首先抓取git fetch origin
    然后合并git merge origin\master
    然后将master分支推送上去git push origin master
    具体参见第5部分,分布式git。

    git clone

    • git clone remote local: 将repository remote 克隆到 local。local克隆的是remote的当前分支,即如果remote处于branch状态,那么local克隆的也是branch状态,并且不包含主分支。
    • 当在local上完成改动并commit之后,需要请求remote一方pull local一方的改动。
      git pull local master: 完成了两个动作,首先把local中的master 分支fetch到了,然后将改动merge到当前branch中。
    • 在执行pull之前,要将当前branch的内容commit。
    • 一个更保险的做法是先手动fetch,比较一下不同再决定是否merge(可以再pull一下或者merge:git merge FETCH_HEAD)。使用下面的命令:
      git fetch local,fetch得到的节点会以FETCH_HEAD标记。
      git log -p HEAD..FETCH_HEAD: 其中"HEAD..FETCH_HEAD" means "show everything that is reachable from the FETCH_HEAD but exclude anything that is reachable from HEAD"显示只有FETCH_HEAD有而HEAD没有的内容。
      也可以使用HEAD...FETCH_HEAD标记,表示show everything that is reachable from either one, but exclude anything that is reachable from both of them,只显示差异不显示相同的。
      以上命令都可以使用gitk进行图形查看。

    相关文章

      网友评论

        本文标题:git简要学习

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