本文使用命令和命令的基本含义做为标题,旨在快速查找经常使用命令。git
Git 自带一个 git config
的工具来帮助设置配置文件。github
这些变量存储在三个不一样的位置:web
$ git config --system |
$ git config --global |
当前使用仓库的 Git 目录中的 $ git config --local |
咱们也能够不加参数表明从全部配置文件读写文件。app $ git config |
每个级别覆盖上一级别的配置,覆盖关系为local > global > system.ssh
下面举个例子:maven
-- 查看系统配置文件 $ git config --system --list -- 查看用户配置文件 $ git config --global --list -- 查看项目配置文件 $ git config --local --list -- 查看全部配置文件 $ git config --list
此命令能够配合配置文件标识查看不一样级别配置文件内容编辑器
-- 查看系统配置文件 $ git config --system --list -- 查看用户配置文件 $ git config --global --list -- 查看项目配置文件 $ git config --local --list -- 查看全部配置文件 $ git config --list
此命令用于修改配置文件内容。
可使用配置文件标识修改指定配置文件内容。
$ git config --global user.name "lic"
通常咱们总会有些文件无需归入 Git 的管理,也不但愿它们总出如今未跟踪文件列表。 一般都是些自动生成的文件,好比日志文件,或者编译过程当中建立的临时文件等。 在这种状况下,咱们能够建立一个名为.gitignore
的文件,列出要忽略的文件模式。
例子忽略了IDEA、maven、日志和svn生成的文件。
# --> IDEA .idea/ *.iml # --> maven target/ # --> log logs/ # --> svn .svn/
使用此命令能够获取到git关于此命令的帮助手册
$ git help config
若是你打算使用 Git 来对现有的项目进行管理,你只须要进入该项目目录并输入
$ git init
该命令将建立一个名为 .git
的子目录,这个子目录含有你初始化的 Git 仓库中全部的必须文件,这些文件是 Git 仓库的骨干。
“.git”目录中的文件结构以下
$ ls config description HEAD hooks/ info/ objects/ refs/
config | git配置文件 |
description | 仓库的描述信息,主要给gitweb等git托管系统使用 |
HEAD | 这个文件包含了一个档期分支(branch)的引用 |
hooks/ | 这个目录存放一些shell脚本,能够设置特定的git命令后触发相应的脚本;在搭建gitweb系统或其余git托管系统会常常用到hook script |
info/ | 包含仓库的一些信息 |
objects/ | 全部的Git对象都会存放在这个目录中,对象的SHA1哈希值的前两位是文件夹名称,后38位做为对象文件名 |
refs/ | 这个目录通常包括三个子文件夹,heads、remotes和tags,heads中的文件标识了项目中的各个分支指向的当前commit |
这是个多功能命令:能够用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。 将这个命令理解为“添加内容到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。
放在项目目录下的文件默认状况下是不受Git管理的,你可经过 git add
命令来实现对指定文件的跟踪。
-- 添加某个文件 $ git add README.md -- 添加所有文件(.为通配符) $ git add .
若是你想得到一份已经存在了的 Git 仓库的拷贝,这是就要使用此命令。
这是 Git 区别于其它版本控制系统的一个重要特性,Git 克隆的是该 Git 仓库服务器上的几乎全部数据,而不是仅仅复制完成你的工做所须要文件。 当你执行 git clone
命令的时候,默认配置下远程 Git 仓库中的每个文件的每个版本都将被拉取下来。 事实上,若是你的服务器的磁盘坏掉了,你一般可使用任何一个克隆下来的用户端来重建服务器上的仓库
Git 支持多种数据传输协议。 https://
协议、 git://
协议以及SSH协议。使用SSH协议时须要在远程仓库配置本机公钥才能生效。
-- https协议 git clone https://git.oschina.net/imlichao/git-example.git -- SSH协议 git clone git@git.oschina.net:imlichao/git-example.git
要查看哪些文件处于什么状态,能够用此命令。
$ git status
提示主要有一下几部份内容:
-- 所在分支和跟踪分支 On branch dev_5.2 Your branch is up-to-date with 'origin/dev_5.2'. -- 没有文件变动 nothing to commit, working tree clean -- 未被Git管理文件(能够git add添加跟踪) Untracked files: (use "git add <file>..." to include in what will be committed) documents/new_file nothing added to commit but untracked files present (use "git add" to track) -- 没有提保存暂存区的文件(能够git add保存到暂存区、git checkout放弃修改、git commit -a直接提交) 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.md no changes added to commit (use "git add" and/or "git commit -a") -- 暂存区未提交的文件(能够git reset HEAD返回工做区) Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: README.md -- 未推送到远程分支的提交数量(能够git push推送到远程分支) On branch dev_5.2 Your branch is ahead of 'origin/dev_5.2' by 1 commit. (use "git push" to publish your local commits) nothing to commit, working tree clean
git status
命令的输出十分详细,但其用语有些繁琐。 若是你使用 git status -s
命令或 git status --short
命令,你将获得一种更为紧凑的格式输出。 运行 git status -s
,状态报告输出以下:
$ git status -s M README MM Rakefile A lib/git.rb M lib/simplegit.rb ?? LICENSE.txt
新添加的未跟踪文件前面有 ??
标记,新添加到暂存区中的文件前面有 A
标记,修改过的文件前面有 M
标记。 你可能注意到了 M
有两个能够出现的位置,出如今右边的 M
表示该文件被修改了可是还没放入暂存区,出如今靠左边的 M
表示该文件被修改了并放入了暂存区。 例如,上面的状态报告显示: README
文件在工做区被修改了可是尚未将修改后的文件放入暂存区,lib/simplegit.rb
文件被修改了并将修改后的文件放入了暂存区。 而 Rakefile
在工做区被修改并提交到暂存区后又在工做区中被修改了,因此在暂存区和工做区都有该文件被修改了的记录。
咱们要比较工做区、暂存区以及仓库分支中文件的差别时可使用此命令。
下面的命令若是不加<file name>表示比较全部文件差别
$ git diff README.md
$ git diff dev_5.2 README.md
$ git diff --cached README.md
和--cached同样两种方式一种效果
$ git diff --staged README.md
$ git diff --cached master README.md
$ git diff dev_5.2 master README.md
如今的暂存区域已经准备稳当能够提交了。 在此以前,请必定要确认还有什么修改过的或新建的文件尚未git add
过,不然提交的时候不会记录这些还没暂存起来的变化。 这些修改过的文件只保留在本地磁盘。 因此,每次准备提交前,先用 git status
看下,是否是都已暂存起来了, 而后再运行提交命令 git commit
git commit
这种方式会启动文本编辑器以便输入本次提交的说明。(提交说明必需要填)
咱们也能够直接使用 -m 参数直接填写说明
git commit -m "commit explain"
尽管使用暂存区域的方式能够精心准备要提交的细节,但有时候这么作略显繁琐。 Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给 git commit
加上 -a
选项,Git 就会自动把全部已经跟踪过的文件暂存起来一并提交,从而跳过 git add
步骤:
$ git commit -a
要从 Git 中移除某个文件,就必需要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),而后提交。 能够用 git rm
命令完成此项工做,并连带从工做目录中删除指定的文件,这样之后就不会出如今未跟踪文件清单中了。
$ git rm documents/test
因为git rm是从暂存区域移除,回退操做要使用git reset HEAD从暂存区撤销,再用git checkout -- 恢复工做区文件。若是已经提交可使用git reset进行回退。
-- 已删除文件恢复到工做区 $ git reset HEAD documents/test Unstaged changes after reset: D documents/test
-- 已删除文件恢复到暂存区 $ git checkout -- documents/test
文件file path移动到path目录。
$ git mv documents/new ./
文件名从file name更改成new name
$ git mv new new1
实际上至关于执行了如下操做
$ mv README.md README $ git rm README.md $ git add README
默认不用任何参数的话,git log
会按提交时间列出全部的更新,最近的更新排在最上面。 正如你所看到的,这个命令会列出每一个提交的 SHA-1 校验和、做者的名字和电子邮件地址、提交时间以及提交说明。
此命令展现提交历史时附带内容差别
$ git log -p
展现提交历史时附带统计信息。如那个文件变化几行,增长内容仍是减小内容等信息。
git log --stat
这个选项能够指定使用不一样于默认格式的方式展现提交历史。 这个选项有一些内建的子选项供你使用。 好比用 oneline
将每一个提交放在一行显示,查看的提交数很大时很是有用。 另外还有 short
,full
和 fuller
能够用,展现的信息或多或少有些不一样,请本身动手实践一下看看效果如何。
$ git log --pretty=oneline
当 oneline 或 format 与另外一个 log
选项 --graph
结合使用时尤为有用。 这个选项添加了一些ASCII字符串来形象地展现你的分支、合并历史:
$ git log --graph
$ git log -- documents/test
$ git log -S "git"
cherry-pick容许咱们提取一个或多个现有的提交,并使用这些提交的快照来建立新的提交。这个功能在处理生产bug时将会很是有用。
$ git cherry-pick 3016bb0b1a3deede145d5f93773ffc7928f22e73 [master 4aff2cc] experiment Date: Mon Apr 16 10:48:55 2018 +0800 2 files changed, 3 insertions(+), 1 deletion(-)
因为使用cherry-pick建立的提交标识名都是一致的,因此两个应用了同一提交的分支在合并时并不会产生冲突,git会完美的将他处理成一次提交。
将HEAD指针和当前分支指针回退一个提交版本。
一个“^”符号表明回退一个版本,三个就回退三个版本。
$ git reset HEAD^
咱们能够制定回退到某一次提交
$ git reset 3016bb0
此命令用于查看操做日志。git全部的操做在这里都能找到。
$ git reflog 3016bb0 (HEAD -> bug) HEAD@{0}: reset: moving to 3016bb0 5e96789 HEAD@{1}: reset: moving to HEAD^ 3016bb0 (HEAD -> bug) HEAD@{2}: reset: moving to 3016bb0 3016bb0 (HEAD -> bug) HEAD@{3}: reset: moving to HEAD^ b5b1cff HEAD@{4}: checkout: moving from master to bug 6bef1e9 (master) HEAD@{5}: commit: experiment
若是咱们将已提交代码进行了回退可是,发现回退错了。这时候在 git log中是没法找到记录的。这是咱们就可使用reflog命令查找到那次提交记录,而后用reset命令指定到回退前的提交编号。 以下图: |
此命令使用了checkout其实真正的含义是,从上次提交的文件从新检出。你须要知道 git checkout -- [file]
是一个危险的命令,这很重要。 你对那个文件作的任何修改都会消失 - 你只是拷贝了另外一个文件来覆盖它。 除非你确实清楚不想要那个文件了,不然不要使用这个命令。
$ git checkout -- README.md
撤销全部工做区修改
$ git checkout -- .
文件从暂存区撤销到工做区
$ git reset HEAD README.md Unstaged changes after reset: M README.md
撤销全部暂存区修改
$ git reset HEAD .
有时候咱们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,能够运行带有 --amend
选项的提交命令尝试从新提交
$ git commit --amend
这个命令会将暂存区中的文件提交。 若是自上次提交以来你还未作任何修改(例如,在上次提交后立刻执行了此命令),那么快照会保持不变,而你所修改的只是提交信息。
有时,当你在项目的一部分上已经工做一段时间后,全部东西都进入了混乱的状态,而这时你想要切换到另外一个分支作一点别的事情。 问题是,你不想仅仅由于过会儿回到这一点而为作了一半的工做建立一次提交。 针对这个问题的答案是 git stash
命令。
储藏会处理工做目录的脏的状态 - 即,修改的跟踪文件与暂存改动 - 而后将未完成的修改保存到一个栈上,而你能够在任什么时候候从新应用这些改动。
须要注意的是工做区和暂存区的代码会所有被贮藏。
git stash
git stash save "stash注释"
$ git stash list stash@{0}: WIP on master: 5e96789 experiment stash@{1}: WIP on master: 5e96789 experiment stash@{2}: On bug: Uncommitted changes before rebase
若是想要应用其中一个更旧的储藏,能够经过名字指定它,像这样:git stash apply stash@{2}
。 若是不指定一个储藏,Git 认为指定的是最近的储藏
恢复的时候若是不加参数将会将储藏得全部内容恢复到工做区,若是增长了--index参数则会分别恢复到红做区和暂存区。
$ git stash apply stash@{2}
就像apply同样将内容恢复,可是回复后的内容将从储藏区删除。
$ git stash pop stash@{2}
将储藏区全部内容所有清空,一旦清空这些代码将永久丢失。因此要当心。
$ git stash clear
$ git stash drop <stash@{id}>
若是想查看你已经配置的远程仓库服务器,能够运行 git remote
命令。 它会列出你指定的每个远程服务器的简写。 若是你已经克隆了本身的仓库,那么至少应该能看到 origin - 这是 Git 给你克隆的仓库服务器的默认名字
$ git remote origin
你也能够指定选项 -v
,会显示须要读写远程仓库使用的 Git 保存的简写与其对应的 URL。
$ git remote -v origin ssh://git@192.168.17.247:10022/PL_service_department/pmall.git (fetch) origin ssh://git@192.168.17.247:10022/PL_service_department/pmall.git (push)
建立一个新的远程仓库
$ git remote add pb https://github.com/paulboone/ticgit
$ git remote rename origin origin1
git remote rm origin1
这个命令会访问远程仓库,从中拉取全部你尚未的数据。 执行完成后,你将会拥有那个远程仓库中全部分支的引用,能够随时合并或查看。
必须注意 git fetch
命令会将数据拉取到你的本地仓库 - 它并不会自动合并或修改你当前的工做。 当准备好时你必须手动将其合并入你的工做。
$ git fetch
此命令是仓库级别的,fatch会将全部分支的变动都拉下来。
指定拉取代码的仓库名称
$ git fetch origin
从远程仓库拉取变动并自动合并当前分支。pull命令会先执行fetch命令将远程仓库的变动拉取到本地,而后尝试将当前分支与对应的跟踪分支进行merge合并。
$ git pull
这里注意fatch是仓库级别的而pull是分支级别的。
当咱们但愿拉取分支后执行的不是merge而是rebase时咱们可使用此命令
git pull --rebase
咱们也能够修改配置文件让pull默认执行rebase
git config --global pull.rebase true
拉取后与指定分支进行合并
$ git pull origin dev_5.3
当你想分享你的项目时,必须将其推送到远程分支。此命令将当前分支推送至跟踪的远程分支。
git push
这里注意fatch是仓库级别的而push是分支级别的。
当前分支推送到指定的分支
git push origin master
当本地分支与远程分支不一样名时使用此命令
git push origin mymaster:master
将本地建立的分支推送到远程仓库
git push -u origin <branch name>
-u 表示添加本地分支与远程分支的跟踪分支。
咱们也能够建立与本地分支不一样名的远程分支
git push -u origin mymaster:master
git push origin --delete serverfix
将一个空分支推送给远程分支实现删除操做。
git push origin :master
这个命令以字母顺序列出标签;可是它们出现的顺序并不重要。
$ git tag
$ git tag -n
你也可使用特定的模式查找标签。 例如,Git 自身的源代码仓库包含标签的数量超过 500 个。 若是只对 1.8.5 系列感兴趣,能够运行:
$ git tag -l 'v1.8.5*'
一个轻量标签很像一个不会改变的分支 - 它只是一个特定提交的引用。与svn不一样git的标签是不能够移动的。
$ git tag v6.0
附注标签是存储在 Git 数据库中的一个完整对象。 它们是能够被校验的;其中包含打标签者的名字、电子邮件地址、日期时间;还有一个标签信息;而且可使用 GNU Privacy Guard (GPG)签名与验证。
$ git tag -a v1.4 -m 'my version 1.4'
你也能够对过去的提交打标签。
$ git tag -a v1.2 9fceb02
$ git tag -d v6.0 Deleted tag 'v6.0' (was e26bdca)
$ git push origin v5.5
$ git push origin --tags
将一个空标签推送给远程分支实现删除操做。
git push origin :v1.0.0
git checkout -b master v6.0
$ git branch dev_5.2 * master
建立分支时会在当前所在的提交对象上建立一个指针。
建立分支时很容易被理解成从当前分支建立一个分支,其实git并无考虑分支之间的关系。只不过当前分支也凑巧指向了当前所在的提交,因此只是建立了指向当前提交的指针与其它分支无关。
git branch -d hotfix
$ git branch -v * bug1 fe13e9b 生产环境修改一个bug dev_5.2 fe13e9b [ahead 5] 生产环境修改一个bug master fe13e9b [ahead 5] 生产环境修改一个bug
从远程分支建立的本地分支,都会自动建立一个跟踪分支来维护本地分支与远程分支的对应关系。
咱们在pull或push代码时就会与对应的远程分支进行交互。
$ git branch -vv * bug1 fe13e9b 生产环境修改一个bug dev_5.2 fe13e9b [origin/dev_5.2: ahead 5] 生产环境修改一个bug master fe13e9b [origin/master: ahead 5] 生产环境修改一个bug
这会将全部的本地分支列出来而且包含更多的信息,如每个分支正在跟踪哪一个远程分支与本地分支是不是领先、落后或是都有。
咱们想本身指定本地分支的远程跟踪分支时使用此命令
$ git branch --set-upstream-to=origin/dev_5.2 Branch bug1 set up to track remote branch dev_5.2 from origin.
$ git branch -a * bug1 dev_5.2 master remotes/origin/HEAD -> origin/master remotes/origin/dev_5.2 remotes/origin/master
$ git branch --merged
$ git branch --no-merged
Git有一个名为HEAD的特殊指针,指向当前所在的本地分支(译注:将 HEAD
想象为当前分支的别名)。
切换分支就是将HEAD指针指向目标分支而已。
git checkout testing
分支切换会改变你工做目录中的文件 在切换分支时,必定要注意你工做目录里的文件会被改变。 若是是切换到一个较旧的分支,你的工做目录会恢复到该分支最后一次提交时的样子。 若是 Git 不能干净利落地完成这个任务,它将禁止切换分支。 |
想要新建一个分支并同时切换到那个分支上,你能够运行一个带有 -b
参数的 git checkout
命令
$ git checkout -b bug1 Switched to a new branch 'bug1'
$ git checkout -b master1 origin/master Switched to a new branch 'master1' Branch master1 set up to track remote branch master from origin.
咱们想将出现分叉提交的分支整合在一块儿时,可使用合并(merge)操做来完成。
Git 会使用两个分支的末端所指的快照以及这两个分支的工做祖先,作一个简单的三方合并。
$ git merge hotfix
快进合并(fast-forward) 当你试图合并两个分支时,若是顺着一个分支走下去可以到达另外一个分支,那么 Git 在合并二者的时候,只会简单的将指针向前推动(指针右移),由于这种状况下的合并操做没有须要解决的分歧——这就叫作 “快进(fast-forward)”。 master只要向前推动就能够完成与iss53的合并,因此会使用快进合并。 |
有时候合并操做不会如此顺利。 若是你在两个不一样的分支中,对同一个文件的同一个部分进行了不一样的修改,Git 就无法干净的合并它们。在合并它们的时候就会产生合并冲突。
解决冲突步骤:
一、须要手动解决冲突并标记已解决。
$ git add README.md
二、须要本身提交新的合并提交。
$ git commit
你能够提取在一个分支中引入的补丁和修改,而后在另外一个分支的基础上应用一次。 在 Git 中,这种操做就叫作 变基。
Git变基时咱们要分清,那个分支产生了补丁,那个分支是基底分支。
$ git rebase master First, rewinding head to replay your work on top of it... Applying: experiment
上例的当前分支(experiment)为补丁分支,rebase后面跟基底分支(master)。也就是说用experiment分支的提交建立补丁,在master分支上从新执行一遍。
从上图能够看出,分叉提交C4不见了,在C3后面从新提交了C4'。master基底分支指针不移动,experiment补丁分支指针指向C4'。
最后若是咱们想要让master分支指针也指向最新提交C4',咱们能够切换到master分支执行快进合并(fast-forward)。
$ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 6 commits. (use "git push" to publish your local commits) $ git merge experiment Updating 4f3f69a..373256b Fast-forward README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
咱们能够指定补丁分支变基到基底分支上。
$ git rebase master experiment First, rewinding head to replay your work on top of it... Applying: experiment
还有一种更加复杂的用法。从master分支建立server分支,从server分支建立client分支。
若是咱们想将client相对于server的不一样提交变基到,master上咱们能够这样使用。
$ git rebase --onto master server client
在变基时若是发现补丁分支快照与基底分支快照存在冲突,变基会中止而且要求手动解决冲突。
变基中止时咱们可使用--continue | --abort | --skip参数来控制变基行为。
$ git rebase --continue
处理完冲突后使用此命令继续变基
$ git rebase --abort
放弃本次变基,还原成变基以前的样子
$ git rebase --skip
放弃补丁版本快照,继续使用基底版本快照。
交互式变基使用屡次提交,从新创建提交。提交重建范围为没有push到远程分支的提交。
$git rebase -i
如今咱们要对每次提交设置命令。通常的合并咱们会将第一次提交选择为pick然后面的提交选择为squash。这样就会用全部的提交生成一次新的提交。
pick 4f3f69a experiment pick 373256b experiment pick 3258dad experiment pick 167f684 experiment pick cd871a6 experiment pick d06c0a0 experiment pick 9f3e252 experiment # Rebase 1221f68..9f3e252 onto 1221f68 (12 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
而后系统提示从新编辑提交说明。(被合并的提交说明会默认按顺序添加)
最后咱们使用git log查看提交日志发现已经剩下一次提交了。
咱们在进行交互式变基的时候能够指定变基提交的次数。HEAD参数后面每增长一个“^”符号表明向后提取一次分支。
$ git rebase -i HEAD^^^^^
这个命令表明从当前提交向后获取5次提交进行交互式变基。