前言
Git官方参考文档为:https://git-scm.com/docs。里面列出了Git所有命令及其详尽说明。实际上,大家也不需要去访问网站,Git软件本身就自带说明文档,大家直接查看本地说明文档即可。比如 diff 这个命令,我们输入
git diff --help
Git 命令操作区域关系:
初次运行 Git 前的配置
安装完 Git 之后,必做的第一件事就是设置你的用户名和邮件地址。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改:
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
git 常用指令
git config
用于配置git软件的一些参数。
- 设置邮箱和用户名(记得换成你自己的邮箱和用户名)
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
- 默认分支名字改为 main
git config --global init.defaultBranch main
- 设置 http 代理或者 vpn
git config https.proxy 127.0.0.1:7890
git config http.proxy 127.0.0.1:7890
- 取消 http 代理或者 vpn 设置
git config --unset http.proxy
git config --unset https.proxy
- 把 c:/mywork(记得换成你自己的目录哦)设为安全目录
git config --global --add safe.directory c:/mywork
- 所有目录都是安全的
git config --global --add safe.directory "*"
git init
用来创建仓库。
- 在当前目录创建git仓库
git init
- 在新目录 work/repo(记得换成你自己的目录哦)下创建git仓库
git init work/repo
git clone
用于将远程仓库克隆到本地
- 克隆仓库到本地(记得换成你自己的git服务器地址)
git clone https://github.com/username/project.git
- 递归克隆远程仓库,这个远程仓库包含 submodule(记得换成你自己的git服务器地址)
git clone https://github.com/username/project.git --recursive
git add
用于把工作目录更新添加到 index 区(stage区)
- 把工作目录所有修改添加到 index
git add .
- 把指定文件 main.c 添加到 index
git add main.c
git commit
用于把修改提交到仓库
- 把 stage 内容提交到仓库,自动打开系统编辑器以让你输入提交信息
git commit
- 把 stage 内容提交到仓库,自动打开系统编辑器以让你输入提交信息,并署名该提交
git commit -s
- 把 stage 内容提交到仓库,提交信息为"my first repo"
git commit -m "my first repo"
- 把 working directory 里面的修改直接提交到仓库,自动打开系统编辑器以让你输入提交信息
git commit -a
- 把 working directory 里面的修改直接提交到仓库,提交信息为 “updated main.c”
git commit -a -m "updated main.c"
- commit 之后发现还有文件需要修改,修改之后,把本次修改合并在上次 commit 之中,而不是另起一个新 commit,自动打开系统编辑器以让你更新上次的提交信息
git commit --amend
- commit 之后发现还有文件需要修改,修改之后,把本次修改合并在上次 commit 之中,而不是另起一个新 commit,并把提交信息更新为 “updated main.c again”
git commit --amend -m "updated main.c again"
git diff
用来比较两个对象
- 显示所有未添加至 index 的变更
git diff
- 显示所有已添加到 index 但还未 commit 的变更
git diff --cached
- 显示 main 分支与 blinky 分支的不同
git diff main blinky
- 只显示 main 分支与 blinky 分支 src 目录的不同
git diff main blinky -- src/*
- 只统计 main 分支与 blinky 分支的文件差异,不比较内容本身差异
git diff main blinky --stat
- 比较 HEAD 与 d1ba4913a43004bb880707276287b8a9c08b32fc(这是一个对象的 ID,即 hash 值)的差异
git diff d1ba4913
- 将更改输出到 patch.diff 文件
git diff > patch.diff
git reset
用来把 HEAD 指针复位到前面的 commit
- 把 HEAD 复位到 commit:fb863c(这是一个对象的 ID,即 hash 值)状态
git reset --hard fb863c
- 把 main 分支复位到服务器 clone 状态
git reset --hard origin/main
- 复位 index 区
git reset
git status
用于查看当前状态
- 查看 working directory 哪些文件修改了
git status
git rm
用于删除工作目录或者 index 区的文件
- 同时删除 index 和 working tree 里面的 README.rst 文件
git rm README.rst
- 只删除 index 里面的 README.rst,保留 working tree 里面的 README.rst
git rm --cached README.rst
如果只删除 working tree 里面的文件,或者还没有添加到 index 里面的文件,请直接使用操作系统的删除命令
git log
显示提交历史
- 显示提交历史
git log
- 简化显示提交历史
git log --oneline
- 显示提交历史,并统计文件修改情况
git log --stat
- 搜索所有提交历史信息中包含 “blinky” 关键字的提交
git log --grep blinky
git show
用于显示对象信息
- 显示 e56e8a(这是一个对象的 ID,即 hash 值)的信息
git show e56e8a
- 显示 tag v1.0.0 的信息
git show v1.0.0
git tag
用于创建,列出,删除与验证tag对象
- 列出目前仓库包含的tag
git tag
- 给 commit e56e8a(这是一个对象的 ID,即 hash 值)打轻量级的 tag,tag 名称为 v0.1
git tag v0.1 e56e8a
- 给 HEAD 打有注解的 tag,tag 名称为 v1.0.0
git tag -a v1.0.0 -m "git demo release v1.0.0"
- 删掉 tag v0.1
git tag -d v0.1
git branch
git branch用于列出,创建和删除分支。
- 列出所有本地分支
git branch
- 列出所有远程分支(确切说是远程跟踪分支)
git branch -r
- 同时列出本地和远程分支
git branch -a
- 创建一个新分支:feature
git branch feature
- 删除分支:feature
git branch -d feature
- 修改分支 feature 名字为 dev
git branch -m feature dev
- 基于 commit e56e8a(这是一个对象的 ID,即 hash 值)建立分支:feature
git branch feature e56e8a
- 设置当前分支跟踪 origin/blinky,即 origin/blinky 成为它的 upstream
git branch --set-upstream-to origin/blinky
- 删除远程分支 blinky 在本地的 clone
git branch -dr origin/blinky
git checkout
用于切换分支或者恢复工作目录内容
- 切换到 blinky 分支
git checkout blinky
- 切换到 tag:v1.0.0
git checkout v1.0.0
- 创建分支 blinky 并切换到此分支
git checkout -b blinky
- 把 index 区的 src/main.c 覆盖 working tree 里面的 src/main.c
git checkout -- src/main.c
git merge
用于合并开发历史
- 将远程跟踪分支 origin/main 合并到当前分支
git merge origin/main
- 手动解决冲突后,继续刚才有冲突的 merge,完成 merge 过程
git merge --continue
- 中止刚才有冲突的 merge
git merge --abort
git rebase
用于将当前分支分叉后的所有 commit 重新提交在新分支的末端
- 将当前分支分叉后的所有 commit 重新提交在 main 分支的末端
git rebase main
- 手动解决冲突后继续 rebase 操作以完成整个操作
git rebase --continue
- 跳过本 commit 继续 rebase 过程
git rebase --skip
git remote
用于管理远程跟踪仓库
- 查看当前所有远程跟踪仓库
git remote -v
- 显示远程仓库 origin 的信息
git remote show origin
- 将 https://github.com/username/project.git 设为远程跟踪仓库,并命名为 origin 或 mirror
git remote add origin https://github.com/username/project.git
git remote add mirror https://github.com/username/project.git
- 删除远程跟踪仓库 origin
git remote remove origin
git push
将本地内容推送到远程服务器
- 将当前分支推送到远程 origin 仓库的 main 分支
git push -u origin main
- 推送所有跟踪分支到远程服务器
git push
- 删除远程服务器的 blinky 分支
git push origin --delete blinky
git fetch
用于下载远程仓库更新到本地
- 下载所有关联的远程仓库
git fetch
- 下载origin仓库的更新到本地 clone 区
git fetch origin
git pull
用于集成远程分支更新到本地分支,是 git fetch 和 git rebase/merge 的合体
- 将当前分支 rebase 到远程跟踪分支 origin/main
git pull --rebase origin main
- 将远程 origin/main 分支 merge 到当前分支
git pull origin main
- 取所有远程分支,并将当前分支的upstream分支merge过来
git pull
git revert
用于覆盖最近几次的提交,即把历史中的一次提交重新在分支顶端提交一次
- 把前一次提交再重新提交一次,相当于前一次提交覆盖了当前提交
git revert HEAD~1
- 把 commit:fb863c(这是一个对象的ID,即hash值)重新提交在分支最顶端
git revert fb863c
git restore
用于恢复工作目录或者 index 区里面的文件
- 将 index 中的 src/main.c 内容恢复到工作区的 src/main.c
git restore src/main.c
- 恢复 index 中的 README.rst 至 HEAD 状态
git restore --staged README.rst
- 将tag:v1.0.0 中的 src/main.c 内容恢复到工作区的 src/main.c
git restore --source=v1.0.0 src/main.c
git reflog
用于管理引用日志信息,包括多个子命令,默认 git reflog 等价于 git reflog show。
- 显示 HEAD 的所有更新操作日志,包括那些删除了或者不可达的 commit
git reflog
- 显示 main 分支的所有更新操作日志,包括那些删除了或者不可达的 commit
git reflog main
git stash
用于将 working tree 的修改暂时压栈
- 将 working tree 里面的修改压入 stash 栈
git stash
- 将 stash 栈中的内容弹出到工作区
git stash pop
- 显示stash栈里面的内容
git stash show
git submodule
用于初始化,更新和查看 submodule
- 把 https://github.com/username/ncs_samples.git 添加为本仓库的子模块并放在 ncs 目录下
git submodule add https://github.com/username/ncs_samples.git ncs
- 从服务器下载 submodule 的更新,如果没有初始化,则对其先进行初始化
git submodule update --init
- 反初始化 ncs 这个 submodule
git submodule deinit ncs
git checkout,git revert 和 git reset 区别
git merge 和 git rebase区别
假设我们有如下分支,即main分支和feature分支,而且他们两个分支都是从同一个commit分叉出来的。
假设我们现在在feature分支上,然后把main分支merge到feature分支上,merge成功后,我们将得到如下分支结构图:
可以看出,merge只创建了一个新commit,而且它的父节点包含2个。
如果我们不使用git merge,而采用git rebase,那么rebase后的分支结构图如下所示:
可以看出rebase后,feature分支以前老的3个commit全部删除,然后他们重新在main分支顶端一一再次提交,形成3个新的commit。Rebase后历史记录呈线性关系,非常干净清晰。
使用git rebase有一条基本原则:不要rebase公共的branch,比如上面的例子,如果我们把main rebase到feature分支上:
执行这个操作后,main分支历史被改写,这样远程的main或者其他开发者的main分支,在Git看来,就跟你的main分支分叉了,后面你就没法直接push了。所以执行git rebase操作的时候,我们总是在开发者分支上进行,然后fast-forward merge到main分支。