Git笔记

Git是什么?

  • 版本控制工具
  • 命令行程序

Git能干什么?

  • 管理代码,控制版本
  • 同步文件

本文不具体介绍怎么使用git,只做基本的概念解说,更多信息请参考git help

Git是怎么工作的

代码仓库(repository)

  进入软件源代码的根目录(项目文件夹),执行git init命令,会生成一个.git目录,.git目录里保存着git工作时所需的所有信息,它就是代码仓库。

文件跟踪(track)

  通过git add <文件名>来跟踪某个文件。一个文件只有被git跟踪才会受到版本控制,可以通过git status命令来查看当前目录下的文件跟踪情况。

git目录里的文件有这么几个状态

  • 未跟踪(untracked) 可以说是从没被git add过的文件
  • 未修改(unmodified) 指自从上次被提交后还没有过改动的文件
  • 已修改(modified) 指自从上次被提交后有过改动的文件
  • 已暂存(staged) 已修改状态的文件再次经过git add后会被暂存

提交(commit)

  软件项目每完成一个阶段(添加了一个功能或者修复了一个bug等),都要提交一次,而且要有提交说明。每一次提交都会将相比上次提交有过改动的文件加入到repository里,可以通过git log命令来查看提交历史。

分支(branch)

  git分支的出现是出于以下的需求:我的程序开发到一个稳定的阶段,我想添加一个新的功能,但是在开发的过程中可能会破坏程序原来的稳定性。怎样才能保证用户能正常使用程序原有的稳定的功能,又不耽误基于现有代码上的新功能的开发呢?如果没有git,我们会考虑将现有的代码拷贝一份保存起来,这样也不是很麻烦,可是我的代码每稳定一次就要完全保存一份,岂不是太麻烦了,而且有很多代码相比上次稳定的没有过改动。
  对于保存改动过的代码,我们自然想到了commit。我们可以把稳定的代码commit了,要用稳定版代码的时候再通过git reset系列命令reset回来。但是这样问题来了,我把开发版的代码reset到稳定版了,我再怎么回到开发版呢?
  于是乎,分支来了。我们可以在主分支上提交过稳定代码过后,通过git checkout -b dev命令新建并切换到dev分支,这样日后我们在dev分支里不管代码有过什么改动,都可以通过git checkout master命令切换到主分支,切换回来后代码会完好如初。用完master的代码,我们随时都可以再通过git checkout dev命令切换到dev分支,代码又变成了你正在开发的版本。等新功能开发完了,我们commit一下,再切换到master分支,用git merge dev命令将dev分支的代码合并过来,至此,我们的新功能才添加到主分支里。至于dev分支,如果不需要了,可以使用git branch -D dev命令删掉。

远程分支(remote branch)

删除远程仓库中的分支

git push :dev ----- 删除远程仓库中的dev分支

Git ignore

  在项目根目录下建立一个.gitignore文件,里面可以存放需要忽略的文件信息。文件名直接写,目录要在目录名后面加斜线/,可以使用通配符,不同的条目之前要单独成行。像下面这样的.gitignore文件:

bin/
test-*.c
bugs.md

  git在跟踪文件会忽略bin目录,所有test-*.c形式的文件以及bugs.md文件,git status命令也不会提示这些文件未跟踪。

Git深入

Git内部对象

  Git将所有的跟踪信息都放在了.git目录里,我们的提交、分支等都是特定的对象,都被git以文件的形式保存在了.git目录里。.git目录像是我们在开发过程中的内存,里面的文件组织结构便是git的数据结构。一般不要直接修改.git目录里的文件,毕竟手动修改'内存'是很危险的,除非你对git内部的工作原理非常熟悉。

  • blob ----- 对应文件
  • tree ----- 对应目录
  • commit ----- 提交
    branch是在内部也是以commit的形式记录,或者说branch是特殊的commit。

杂记

不常用但很有用的命令

没见过的命令要记得git help <>,或者度娘

  • git commit --amend 修定上次提交
  • git ls-tree 列出树对象
  • git clone --depth=1 <url> 只克隆最后一次提交
  • git rebase 删除以前没用的提交
  • git clone --recursive 递归克隆submodule

Git reset 命令的三种方式

  1. git reset –mixed:此为默认方式,不带任何参数的git reset,即时这种方式,它回退到某个版本,只保留源码,回退commit和index信息
  2. git reset –soft:回退到某个版本,只回退了commit的信息,不会恢复到index file一级。如果还要提交,直接commit即可
  3. git reset –hard:彻底回退到某个版本,本地的源码也会变为上一个版本的内容

git revert

Commit关系图

图文来源于StackOverflow: http://stackoverflow.com/questions/2221658/whats-the-difference-between-head-and-head-in-git

G   H   I   J
 \ /     \ /
  D   E   F
   \  |  / \
    \ | /   |
     \|/    |
      B     C
       \   /
        \ /
         A
A =      = A^0
B = A^   = A^1     = A~1
C = A^2  = A^2
D = A^^  = A^1^1   = A~2
E = B^2  = A^^2
F = B^3  = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2  = B^^2    = A^^^2  = A~2^2
I = F^   = B^3^    = A^^3^
J = F^2  = B^3^2   = A^^3^2

最近的一次提交可以用HEAD表示,本例中A就是HEAD。G-D-B-A是主干(master)分支,C是A的次要祖先,B是A的直接祖先,当前分支的上级commit用,其它分支用^。多个、~1、1的效果是一样的,因为git在识别时会从左向右计算。

参考资料

原文地址:https://www.cnblogs.com/luzhlon/p/7055393.html