Git基础

Git会将变化的文件作快照后,记录在微型的文件系统中,保存一个指向这次快照的索引。在保存到git之前,所有数据都要进行内容的校验和(checksum)计算。使用SHA-1算法计算数据的校验和。

文件的三种状态

  • 已提交 commited
  • 已修改 modified
  • 已暂存 staged

文件流转的三个工作区域

  • 工作目录
  • 暂存区域
  • 本地仓库

git工作流程

  • 在工作目录中修改某些文件
  • 对修改后的文件进行快照,保存到暂存区域
  • 提交更新,将保存在暂存区域的文件快照永久转储到git目录中

几个状态:

  • 未跟踪
  • 已跟踪

    • 未修改
    • 已修改
    • 暂存区

添加git-completed

  • brew install bash-completion
  • 添加以下内容到~/.bash_profile

    1
    2
    3
    if [ -f $(brew --prefix)/etc/bash_completion ]; then
    . $(brew --prefix)/etc/bash_completion
    fi
  • cd /usr/local/opt/bash-completion/etc/bash_completion.d

  • curl -L -O https://raw.github.com/git/git/master/contrib/completion/git-completion.bash
  • brew unlink bash-completion
  • brew link bash-completion
  • 重启bash

跟踪新文件

git add将文件转换成已暂存状态,或者跟踪给定目录的文件。

一开始就设置好 .gitignore文件的习惯,以免将来误提交这类无用的文件。

  • 匹配模式最后跟反斜杠(/)说明要忽略的是目录。
  • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。

查看已暂存和未暂存的更新

git diff会使用文件补丁的格式显示具体添加和删除的行。

此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。

若要看已经暂存起来的文件和上次提交时的快照之间的差异,可以用 git diff --cached或者git diff --staged命令。

提交

每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态,或者进行比较。

git commit -a会自动把所有已经跟踪过的文件暂存起来一并提交。

移除文件

git rm可以从暂存区域移除文件,并且连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项-f

如果只想从git仓库删除,暂存区域删除,但是还希望在工作目录中,git rm --cached readme.txt,随后在.gitignore文件中补上

移动文件

Git 并不跟踪文件移动操作。所以需要git mv file_from file_to

提交历史

  • git log
  • git log -p -2展开显示最近两次提交的内容差异
  • git log --stat仅显示简要的增改行数统计

撤销操作

git commit --amend重新提交

  • 取消已经暂存的文件

    git reset HEAD benchmarks.rb

  • 取消对文件的修改

    git checkout -- benchmarks.rb

一些别名

  • git config --global alias.unstage 'reset HEAD --' 这样就可以git unstage readme.md
  • git config --global alias.last 'log -1 HEAD'这样就可以使用git last来查看最后一次提交的内容了
  • git config --global alias.unmodify 'checkout --' 这样就可以使用git unmodify readme.md来返回文件的修改内容了

远程库

查看

  • git remote 查看远程仓库名字,比如origin
  • git remote -v 显示对应的克隆地址
  • git remote add [shortname] [url] 添加一个远程仓库
  • git remote show [remote-name] 查看某个远程仓库的详细信息
  • git remote set-url origin [GIT URL] 修改当前远程库的源地址
  • git remote rename origin origin2 重命名一个远程仓库
  • git remote rm origin 删除一个远程仓库

从远程仓库抓取数据

git fetch origin 从远程仓库拉取本地仓库还没有的数据,包括所有分支,但是这个命令只是将数据拉到本地仓库,但是不会自动合并到当前工作分支。但是git pull就会将数据拿下来,然后将远端分支自动合并到本地仓库当前分支。

推送数据

git push [remote-name] [branch-name] 比如 git push origin master,选择要推送的远程仓库和分支名字,遇到冲突,必须先将更新抓取到本地,合并之后才可以再推送。

将单个文件回退到历史版本

  • git reset a4e215234aa4927c85693dca7b68e9976948a35e book.pdf 第三个为要回退的版本commit id
  • git commit -m "revert book.pdf" 提交
  • git checkout book.pdf 更新到工作目录
  • git push

分支

一次提交会产生三种对象,一种是文件快照内容的blob对象,一种是记录目录树内容和对应文件blob对象索引的tree对象,以及包含tree对象和其他提交元数据的commit对象。

再次提交之后,这次的commit对象就会包含上次提交对象的指针。

分支,本质上是指向commit对象的可变指针。

git branch testing或者git checkout -b testing会创建分支并且切换到这个分支。

另外git还有一个HEAD指针,它指向正在工作的本地分支的指针,也就是当前分支的别名。

经历一段时间的开发之后,就会是这个样子

git merge hotfix将hotfix的分支合并到当前分支来。Fast forward的意思是可以直接顺着合并的分支走下去,也就是要合并的分支的直接祖先就是当前提交对象。

git branch -d hotfix 删除分支

分支的合并

如果要合并的分支的直接祖先不是当前提交对象,那么就会用两个分支的末端和它们的共同祖先来做三方合并计算。git会自动识别最佳同源合并点。然后对合并结果做新的快照,然后创建一个提交对象,这个提交对象有两个祖先。

如果有冲突,手工解决冲突,并且将相关文件暂存,并且创建提交对象,然后完成合并。

分支的管理

  • git branch 列出分支
  • git branch -v 查看分支最后一个提交对象的信息
  • git branch --merged 查看那些分支已经被并入当前分支,也就是那些分支是当前分支的上游
  • git branch --no-merged 查看尚未合并的工作

从远程分支checkout出来的本地分支,为跟踪分支,跟踪分支是一种和某个远程分支有直接联系的本地分支。然后直接git push就可以push到对应分支,git pull会获取对应的远程分支的数据。

克隆的时候,会自动创建一个master的分支跟踪origin/master

但是可能会有其他的一些不一样的地方,比如git fetch origin之后会得到一个新的远程分支origin/serverfix,但是你没有本地的serverfix分支,所以可以

  • git merge origin/serverfix
  • git checkout -b serverfix origin/serverfix
  • git checkout --track origin/serverfix

然后推送的时候可以指定本地分支和远程分支:git push origin master:master

分支的衍合

也就是在一个分支的提交内容在当前分支再进行一遍,这样的好处是分支历史是一条直线。git rebase experiment

储藏(stashing)

可以获取你工作目录的中间状态,修改过的被追踪文件和暂存的变更,保存到未完结变更的堆栈中。

git stash 就可以储藏变更。git stash list查看现有的储藏。应用储藏git stash apply stash@{2},如果直接git stash apply就会使用最近的储藏。即使使用了最近的储藏,这个储藏也不会消失,仍然会保存着。删除的话使用git stash drop stash@{0},可以使用git stash pop应用储藏,并且从堆栈中拿走。

而且对文件的变更会被重新应用,被暂存的文件没有重新被暂存。如果想要重新应用被暂存的变更,git stash apply --index

其中WIP是Work in Process。

取消储藏

应用储藏之后有修改,但是又要取消储藏的修改。也就是弃用储藏的修改。

git stash show -p stash@{0} | git apply -R

也可以加一个别名git config --global alias.stash-unapply 'git stash show -p | git apply -R'

然后可以再git stash apply再恢复储藏

重写历史

改变最近一次提交

git commit --amend修改最近一次的提交说明,并且如果有文件在暂存区的时候,就会将其提交,作为新提交的快照。但是如果push上去了,就不要改上次的提交了。