前言
这一部分内容主要记录git使用时的重要命令,文章参考:
- MIT Missing class
- Git Pro
Basic
git help \<command>
: get help for a git commandgit init
: creates a new git repo, with data stored in the .git directorygit status
: tells you what’s going ongit add <filename>
: adds files to staging areagit commit
: creates a new commitgit log
: shows a flattened log of historygit log --all --graph --decorate
: visualizes history as a DAGgit diff
: show changes you made relative to the staging areagit diff <revision> <filename>
: shows differences in a file between snapshotsgit checkout <revision>
: updates HEAD and current branchgit reset HEAD <FILE>
:unstage the file
Explanation:
- git init 会创建一个名为.git的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件。
- git add *.c 将已经存在的文件加入Stage(暂存区)开始追踪这些文件,或者精确地将内容添加到下一次提交中。git add 命令使用文件或目录的路径作为参数;如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件。
我开始一直没想明白为啥不可以commit的时候选择一些文件,这样也同样可以达到commit部分文件的效果。后面发现git add可以对stage内容进行反复修改,git add根据文件最新的数据生成snapshot(blob|tree),但是不会存入到git repo中,我一定程度上理解了stage存在的必要性。 假设你在开发feature1,你完成了一部分工作但是并没有全部完成,这时候的内容不应该被添加到commit chain中,因为这不是一个完整的可用的实现,但是通过git add添加到stage就不存在这个担心,这个有两个好处,一个是当你后续开发完feature1时,可以再次git add进stage,然后commit上去一个最终确定的版本;另一个是当你接下去开发时发现出问题了,想回到git add时暂存的状态,因为这个是正确的,那么可以通过git restore来抛弃在工作目录中新增的修改。 如果这里用commit去保存feature1的部分代码,然后再用第二次commit保存第二次代码,这样会出现很多的snapshot上的重复(应该吧)。
这里也体现了git设计和使用的哲学,commit提交的,是确定可行的完整实现,如果没有完成,用git add来暂存。
- git diff 不加任何参数比较的是工作目录中当前文件和暂存区域快照之间的差异。 也就是修改之后还没有暂存起来的变化内容。若要查看已暂存的将要添加到下次提交里的内容,可以用
git diff --staged
命令。 这条命令将比对已暂存文件与最后一次提交的文件差异。请注意,git diff
本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。 所以有时候你暂存了所有更新过的文件,运行git diff
后却什么也没有,就是这个原因。 - git commit 当暂存区已经准备就绪,可以提交了。 在此之前,请务必确认还有什么已修改或新建的文件还没有 git add 过, 否则提交的时候不会记录这些尚未暂存的变化。不加任何参数的
git commit
会启动你选择的文本编辑器来输入提交说明。在提交的时候,给git commit
加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤。 - git log 打印commit的信息,
-<n>
显示最近n条的commit信息,参数-p
显示diff信息,参数--since=2008-01-15
显示这一天之后的commit,参数--stat
显示精简后的信息。下面的例子显示的是筛选了作者,时间,但没有合并的commit的git log用法
$ git log --pretty="%h - %s" --author='Junio C Hamano' --since="2008-10-01" --before="2008-11-01" --no-merges -- t
Branching and merging
git branch
: shows branchesgit branch <name>
: creates a branchgit branch -d <name>
: delete a branchgit checkout -b <name>
: creates a branch and switches to it, same asgit branch <name>; git checkout <name>
git merge <revision>
: merges into current branchgit mergetool
: use a fancy tool to help resolve merge conflictsgit rebase
: rebase set of patches onto a new base
Explanation:
分支实际上就是一个指向commit的指针,创建一个新的分支实际上就是在当前的commit上新建一个指针,在某一个分支上开发实际上就是这个指针以前一个commit为parent不断继续创建新的commit,head表示的其实指向当前所在的本地分支的指针。删除分支也只是删除指针,而不是删除commit
git merge <revision>
会合并分支,合并过程中出现fast-forwad表示由于你想要合并的分支所指向的提交 C4 是你所在的提交 C2 的直接后继,
after merge
如果合并的分支没有后继的关系,例如
合并后的会生成一个新的commit,这次提交的特别之处在于有多个不同的父提交
- 有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。 如果你对 issue53问题的修改和有关 hotfix 分支的修改都涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突:
Remotes
git remote
: list remotesgit remote add <name> <url>
: add a remotegit push <remote> <local branch>:<remote branch>
: send objects to remote, and update remote referencegit branch --set-upstream-to=<remote>/<remote branch>
: set up correspondence between local and remote branchgit fetch
: retrieve objects/references from a remotegit pull
: same as git fetch; git mergegit clone
: download repository from remote
Explanation
- git remote列出的是仓库服务器的名字,例如origin,这是默认名字 。你也可以指定选项
-v
,会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL。 - git remote add <shortname> <url> 添加一个新的远程 Git 仓库,同时指定一个方便使用的简写
- git fetch <remote> 这个命令会访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。必须注意
git fetch
命令只会将数据下载到你的本地仓库——它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。运行git pull
通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支。 git push <remote> <branch>
当你想要将 master 分支推送到 origin 服务器时(再次说明,克隆时通常会自动帮你设置好那两个名字), 那么运行这个命令就可以将你所做的备份到服务器。- 如果想要查看某一个远程仓库的更多信息,可以使用
git remote show <remote>
命令 git remote remove | git remote rm
: 如果因为一些原因想要移除一个远程仓库——你已经从服务器上搬走了或不再想使用某一个特定的镜像了, 又或者某一个贡献者不再贡献了——可以使用git remote remove 或 git remote rm
Undo
git commit --amend
: edit a commit’s contents/messagegit reset HEAD <file>
: unstage a filegit checkout -- <file>
: discard changes
Explanation
- git commit --amend用于当忘记将一部分修改过的文件放入stage然后commit时,它会撤销上次的commit,将后面添加stage内容重新生成一次commit。
- git reset HEAD <file> 会将暂存区的文件删除
- git checkout – <file> 会删除掉工作目录的改动,从暂存区中恢复工作目录
Advanced Git
git config
: Git is highly customizablegit clone --depth=1
: shallow clone, without entire version historygit add -p
: interactive staginggit rebase -i
: interactive rebasinggit blame
: show who last edited which linegit stash
: temporarily remove modifications to working directorygit bisect
: binary search history (e.g. for regressions).gitignore
: specify intentionally untracked files to ignore
git的内容很多,想要详细需要细看书里的内容