git 常用指令

1. 移除/移动

要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。

1.1 移除文件

$ git rm [文件/目录/global模式] # 目录需加 -r 选项

$ git rm -f [文件/目录/global模式]    # 强制删除, 删除之前修改过并且已经放到暂存区域

$ git rm -r -n --cached [文件/目录] # -n 不删除任何文件,展示要删除的文件列表

$ git rm --cached [文件/目录/global模式]   # 让文件保留在磁盘, 但并不让Git继续跟踪。
                            # 即把文件从 Git 仓库中删除,但仍然保留在当前工作目录中。

1.2 移动文件

$ git rm [src_file] [dst_file]

# 相当于

$ mv [src_file] [dst_file]
$ git rm [src_file]
$ git add [dst_file]

2. 查询指令

2.1 文件状态

$ git status    # 显示当前工作目录和暂存区的状态

2.2 修改内容

$ git diff  # 本地库 vs 暂存区快照 (index), 即本地库修改之后未暂存的内容

$ git diff --star   # 查看简单的 diff 结果

$ git diff --cached # 已暂存 (staged) vs 上次提交时的快照 (HEAD)
                    # 即下一次提交时会提交到HEAD的内容

$ git diff --staged # 已暂存 (staged) vs 上次提交时的快照 (HEAD)
                    # 即下一次提交时会提交到HEAD的内容

$ git diff release master   # 将两个分支上最新的提交做 diff
$ git diff release..master  # 将两个分支上最新的提交做 diff

$ git diff release...master # 自 release和 master 分别开发以来,master分支上的变更

$ git diff release  # 当前分支与 release 分支的差别

$ git diff HEAD # 本地库 vs HEAD

$ git diff HEAD^ HEAD   # 比较上次提交和上上次提交

$ git diff [commit-id] [commit-id]  # 比较两次提交之间的差异

$ git diff HEAD -- ./lib    # 当前分支目录下的lib目录与上次提交之间的差别

2.3 远程库

$ git remote    # 查看已配置的远程仓库服务器, "origin" Git克隆的仓库服务器默认的名字

$ git remote -v # 显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL

$ git remote show [remote-name] # 查看某远程仓库的更多信息

3. 远程操作

3.1 pull 远程库→工作区

git pull 等同于 git fetch + git merge

$ git pull  # 从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支

$ git pull --rebase origin master
# 拉取已修改的远程库是, 会产生一个merge commit
# rebase 选项是把本地提交一次一个地迁移到更新了的中央仓库master分支之上
# rebase过程中有冲突时, 会在有冲突的提交处暂停rebase过程
# 出现冲突时(不同分支修改同一个文件时可能出现):
# git status    # 查看冲突文件 -- unmerged paths 中
# git add [file]    # 就该冲突文件后暂存
# git rebase --continue # 继续, 以完成剩下的工作
# git rebase --abort    # 回到你执行git pull --rebase命令前的样子

$ git pull origin next:master   # 取回origin主机的next分支,与本地的master分支合并

$ git pull origin next  # 取回origin主机的next分支, 与当前分支合并

$ git pull origin   # 当前分支与远程分支存在追踪关系,git pull就可以省略远程分支名。
# 本地的当前分支自动与对应的origin主机 ”追踪分支 ”(remote-tracking branch)进行合并。

$ git pull  # 当前分支只有一个追踪分支, 可省略远程主机名
            # 当前分支自动与唯一一个追踪分支进行合并

# 如果合并需要采用rebase模式,可以使用–rebase选项。
$ git pull --rebase <远程主机名> <远程分支名>:<本地分支名>

3.2 fetch/clone 远程库→本地库

$ git clone [url] [shortname]   # 把远程仓库克隆到本地, shortname 默认为 origin

$ git clone -l -s -n . ../copy  # 在当前目录中使用克隆

# 从现有本地目录借用从上游克隆
$ git clone --reference /git/linux.git
    git://git.kernel.org/pub/scm/.../linux.git
    mydir

# 创建一个裸存储库以将您的更改发布给公众
$ git clone --bare -l /home/proj/.git /pub/scm/proj.git

git clone 会自动设置本地 master 分支跟踪克隆的远程仓库的 master 分支, 即本地的master分支自动”追踪”origin/master分支, 也可手动建立追踪关系.

$ git branch --set-upstream master origin/next #指定master分支追踪origin/next分支

git fetch具体细节分两步:

  1. 创建并更新本 地远程分支。即创建并更新origin/xxx 分支,拉取代码到origin/xxx分支上。
  2. 在FETCH_HEAD中设定当前分支-origin/当前分支对应,如直接到时候git merge就可以将origin/abc合并到abc分支上。

缺点: git fetch 会拉取当前项目的所有分支的commit。

$ git fetch [url]   # 拉取远程仓库中有但本地仓库没有的文件
                    # git fetch 不会自动合并或修改当前的工作区

$ git fetch origin [branch-name]    # 设定当前分支的 'FETCH_HEAD' 为远程服务器                                          # origin 的branch分支
                                    # 在这种情况下, 不会在本地创建本地远程分支

$ git fetch origin [branch-name1]:[branch-name2]
# 使用远程branch-name1分支在本地创建branch-name2(但不会切换到该分支),
# 如果本地不存在branch-name2分支, 则会自动创建一个新的branch2分支,
# 如果本地存在branch-name2分支, 并且是`fast forward',则自动合并两个分支,否则,会阻止

$ git fetch origin :[branch-name2]
# 等价于: git fetch origin master:branch-name2
$ git remote add [shortname] [url]  # 添加远程仓库
                                # 在命令行中可以使用字符串 shortname 来代替整个 URL
$ git remote rename [old-name] [new-name]   # 重命名远程仓库的简写名

$ git remote rm [remote-name]   # 移除远程仓库

3.3 push 本地库→远程库

使用本地引用更新远程引用,同时发送完成给定引用所需的对象。

$ git push [remote-name] [branch-name] # 将本地的branch-name分支推送到remote-name
                # 服务器. 有所克隆服务器的写入权限,并且之前没有人推送过,才能生效.

$ git push origin :master   # 省略本地分支名,表示删除origin主机的master分支
                            # 推送一个空的本地分支到远程分支

$ git push origin   # 将当前分支推送到origin主机的对应分支
                    # 当前分支与远程分支之间存在追踪关系,本地分支和远程分支都可以省略

$ git push  # 将当前分支推送到origin主机的对应分支
            # 当前分支只有一个追踪分支

# 当前分支与多个主机存在追踪关系
# 使用-u选项设置本地分支去跟踪远程对应的分支
$ git push -u origin master
# 将本地的master分支推送到origin主机,同时指定origin为默认主机.
# 后面就可以不加任何参数使用 git push 了.

$ git push --all origin #不管是否存在对应的远程分支,将所有本地分支都推送到origin主机

$ git push origin [tag_name]    # 推送标签(tag), git push默认不会推送标签

$ git push origin HEAD  # 将当前分支推送到远程的同名

$ git push origin HEAD:master # 将当前分支推送到源存储库中的远程引用匹配主机

3.4 add 工作区→暂存区

默认情况下,git add命令不会添加忽略的文件. 但可以用-f(force)选项添加被忽略的文件。

$ git add [文件或目录]   # 将新文件添加到索引, 开始跟踪新文件,
                        # 把已跟踪的文件放到暂存区,
                        # 合并时把有冲突的文件标记为已解决状态。
        # 如果参数是文件,该命令将跟踪该文件,
        # 如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件。

$ git add -u [目录] # 把目录中所有跟踪文件中被修改过或已删除文件的信息添加到索引库。
                    # 它不会处理那些不被跟踪的文件。省略目录表示当前目录。

$ git add -A [目录] # 把目录中所有跟踪文件中被修改过或已删除文件和所有未跟踪的文件信
                    # 息添加到索引库。它不会处理那些不被跟踪的文件。
                    # 省略目录表示当前目录。

$ git add -i [目录] # 查看中被所有修改过或已删除文件但没有提交的文件,
# 并通过其revert子命令可以查看目录中所有未跟踪的文件,同时进入一个子命令系统。

3.5 commit 暂存区→本地库

将索引的当前内容与描述更改的用户和日志消息一起存储在新的提交中。

$ git commit [文件或目录]   # 把文件或目录下的所有文件,放入下一次提交

$ git commit -a # 跳过 git add, 把所有已经跟踪过的文件暂存起来一并提交

3.6 checkout 本地库→工作区

$ git checkout tag_name # 在当前分支上 取出 tag_name 的版本

4. 提交记录

$ git log   # 按提交时间列出所有的更新

$ git log -p    # 每次提交的内容差异

$ git log -p -2 # 最近两次提交的内容差异

$ git log --stat    # 每次提交的简略的统计信息

$ git log --pretty=oneline  # 提交历史显示模式 oneline (将每个提交放在一行显示)
                            # 其他模式 short,full,fuller

$ git log --pretty=format:"%h - %an, %ar : %s"  # 定制要显示的记录格式

$ git log --pretty=format:"%h %s" --graph # 展示分支、合并历史

$ git show [commit-id]   # 查看某次提交详细信息

5. 撤销

$ git commit --amend    # git commit后, 先运行 git add 添加漏掉的文件再运行此命令
                        # git commit后, 修改提交信息, 再运行此命令

$ git reset HEAD [file] # 取消暂存的文件, git add 后放置于暂存区的文件

$ git reset --soft [commit-id]  # 重置HEAD到commit-id处。
                                # --soft 不改变index和working copy中的文件

$ git reset --keep HEAD # 保留工作区和 HEAD 之间的差异

$ git checkout . # 把当前目录所有修改的文件 从HEAD中签出并且把它恢复成未修改时的样子

$ git checkout  master [file-name]  # 放弃当前对文件file-name的修改

$ git checkout -- [file]    # 撤销对文件的修改, 有两种情况:
                    # 1. 文件修改后未放入暂存区, 撤销修改: 回到和版本库一样的状态
                    # 2. 文件修改后已放入暂存区, 撤销修改: 回到添加到暂存区后的状态

$ git checkout -- '*.c' # 检出索引中的所有C源文件

6. HEAD指针

每个分支都有一个 HEAD 指针, 它指向当前分支的最新提交.

# 查看当前分支 HEAD 指针的 commit id
$ cat .git/refs/heads/master
$ git rev-parse HEAD
$ git rev-parse --short HEAD

$ git show-ref --head   # 查看所有本地库分支、远程库分支、标签所指向的commit id
$ git show-ref --heads  # 查看所有本地库分支所指向的 commit id

$ git reset --soft [commit-id] # 重置 HEAD 指针, 不会破坏任何东西

$ git reset --mixed [commit-id] # 重置 HEAD 指针, 从尚未提交的暂存区域还原这些更改.
                    # 仅从暂存区域恢复更改。对文件的工作副本进行的实际更改不受影响.
                    # 默认Git复位等效于执行 git reset - mixed

$ git reset --hard [commit-id] # 重置 HEAD 指针, 清除暂存区域.
                        # 将 HEAD 指针重置为特定提交ID的最新提交,并删除本地文件更改.

7. 分支

可以从现有的分支创建一个新的分支。 也可以使用特定的提交或标签作为起点创建分支。 如果没有提供任何特定的提交ID,那么将以HEAD作为起点来创建分支。

$ git branch    # 列出所有分支, 当前分支前面标记一个 * 号

$ git branch [branch-name]  # 创建分支--基于当前分支

$ git checkout [branch-name]    # 切换分支

$ git checkout -b [branch-name]   # 创建并切换分支--基于当前分支

git checkout --orphan [branch-name] # 创建并切换分支--无父分支

$ git checkout -b marys master  # 创建y一个基于master分支的marys分支, 并且换到marys

$ git merge [branch-name]   # 合并指定分支到当前分支

$ git branch -m [old-branch] [new-branch]   # 重命名分支

$ git branch -d [branch-name]   # 删除指定分支

$ git push origin [branch-name] # 推送本地分支

$ git push origin --delete [branch-name]    # 删除远程库中指定分支

$ git push origin :[branch-name]    # 推送一个空分支到远程分支,删除远程库中的分支

8. 标签

打标签的操作发生在我们commit修改到本地库之后.

$ git tag -l    # 查看本地库所有可用标签

$ git ls-remote --tags  # 查看远程库所有标签

$ git show [tag-name]   # 查看指定标签的详细信息

$ git tag [tag-name] [commit-id]    # 标记特定提交

$ git tag -a '标签名' -m '标签信息' HEAD    # 创建带有说明的标签, 标记当前HEAD指针

$ git tag -a '标签名' -m '标签信息' [commit-id] # 创建带有说明的标签, 标记特定提交

$ git fetch origin tag [tag-name]   # 获取远程库标签到本地

$ git fetch origin --tags    # 获取所有远程库标签到本地

$ git push origin [tag-name]    # 推送一个本地标签

$ git push origin --tags    # 推送全部未推送过的本地标签

$ git tag -d [tag-name] # 从本地存储库中删除标签

$ git push origin --delete tag [tag-name]   # 从远程储库中删除标签

$ git push origin :refs/tags/[tag-name] # 推送一个空tag到远程 tag, 删除远程标签
                                        # 需先从本地库中删除 tag

9. 补丁

补丁是一个文本文件,其内容类似于git diff,但与代码一样,它也有关于提交的元数据; 例如提交ID,日期,提交消息等。

$ git format-patch -1 # 单次提交, 为最新的提交创建补丁, 会创建.path文件

$ git format-patch [commit-id] -n   # 为指定提交创建补丁,
                                    # n指从commit-id对应的commit开始算起n个提交

$ git format-patch [commit-id] -1   # 为某个提交创建补丁

$ git format-patch [commit-id1] .. [commit-id2] # 为某两次提交之间创建补丁

$ git apply [patch-name]    # 使用补丁, 修改本地文件而不创建提交

$ git am [patch-name]   # 使用补丁, 会修改文件并创建提交

10. 初始化现有仓库

# 普通库
$ git init  # 根文件夹下包括所有的源代码,git版本控制相关的文件在.git目录下
# .git目录以及其下的版本历史记录文件,这些版本历史记录文件就存放在.git目录下

# 裸库
$ git init --bare   # 跟目录下只包括git版本控制相关的文件等。但不包括项目源代码
# 只生成.git目录下面的版本历史记录文件,直接存放在版本库的根目录下面
# 一般用于远端备份或公共版本库
Table of Contents