三种状态
-
已提交(committed)
表示数据已经安全地保存在本地数据库.
-
已修改(modified)
表示修改了文件, 但还没保存到数据库中.
-
已暂存(staged)
表示对一个已修改文件的当前版本做了标记, 使之包含在下次提交的快照中.
三个阶段
-
工作区
工作区是对项目的某个版本独立提取出来的内容.
-
暂存区
暂存区是一个文件, 保存了下次将要提交的文件列表信息.
-
Git 目录(仓库)
Git 仓库目录是 Git 用来保存项目的原数据和对象数据库的地方.
基本的 Git 工作流程
- 在工作区修改文件.
- 将下次想要提交的更改选择性地暂存, 这样只会将更改的部分添加到暂存区.
- 提交更新, 找到暂存区的文件, 将快照永久性存储到 Git 目录.
命令速查
-
初次运行 Git 前的配置
-
1.配置系统变量
# 查看所有配置及其所在的文件 git config --list --show-origin <key> # 配置每个用户的仓库配置 git config --system # 配置当前用户 git config --golbal # 配置当前项目 git config --local
-
- 配置用户信息
# 设置提交时显示的作者名 git config --global user.name "foo" # 设置提交时显示的邮箱 git config --global user.email "baz@bar.com"
-
- 文本编辑器
git config --global core.editor vim
-
- 其他
# 检查配置信息 git config --list # 检查具体的某项配置 git config user.name # 获取帮助 git help <verb> git <verb> --help man git-<verb>
-
获取 Git 仓库
-
将尚未进行版本控制的本地目录转换为 Git 仓库.
git init git init -bare
-
从其他服务器克隆一个已存在的 Git 仓库.
git clone https://github.com/author/project
- 文件状态
-
已跟踪
指被纳入了版本控制的文件.
-
未跟踪
Git 在之前的快照(提交)中没有这些文件.
-
# 检查当前文件状态 git status # 紧凑模式 git status -s # Untracked files 未追踪 # Changes to be committed 已暂存 # Changes not staged for commit 已追踪的文件内容发生了变化(工作区) # 但还没有放到暂存区, 通过 git add 添加到暂存区 # 跟踪新文件/添加至暂存区 git add README.md
- 文件状态
-
-
查看已暂存和未暂存的修改
# 查看工作区当前文件和暂存区之间的差异 git diff # 查看已暂存的文件和最后一次提交之间的差异 git diff --cached # 仅显示变化的文件 git diff --stat
-
提交
# 提交 git commit # 提交(单行描述) git commit -m "baz" # 将已追踪的文件暂存起来一并提交 (git add) git commit -a # 修改上一次提交的描述/提交不保留上一次提交记录 git commit --amend # 重置上一次提交的作者 git commit --amend --reset-author # 修改上一次提交的作者 git commit --amend --author="baz" # 修改上一次提交的时间 git commit --amend --date="baz" # 合并多次提交 # git log # commit1 A.1 --| # commit2 A.2 --| # commit3 A.3 --|--> 合并这 4 个 commit # commit4 A.4 --| # commit5 B.1 git rebase -i commit5 # 需要当前 HEAD 合并到的 commit hash 的前一条 commit hash git rebase -i HEAD~4 # 合并最近 4 条提交 git merge --squash <branch> # 从把其他分支的多条提交压缩成一条 # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # b, break = stop here (continue rebase later with 'git rebase --continue')
-
移除文件
如果直接从工作区删除文件, 运行
git status
后, 文件会显示在 changes note staged for commit(未暂存) 部分.运行
git rm
可以记录此次移除文件的操作(changes to be commited).git rm README.md git rm -f README.md # 删除文件前已缓存或者修改过则必须使用强制删除选项 -f git rm --cached README.md # 从 git 仓库中删除(不删除本地文件)
-
移动文件
git mv readme.md README.md # 重命名
-
查看提交日志
git log -<n> # 查看前 n 条日志 git log -p/--patch -1 # 查看最近一条的提交的差异 git log --stat # 查看提交修改的文件 git log --pretty=oneline # 以一行的方式显示提交描述 git log --oneline # 简写 git log --pretty=format:"%h - %cn, %cd: %s" # 以格式化的方式显示提交信息 git log --since=2.weeks # 查看最近两周的所有提交 git log --until=2.weeks # 查看两周前的所有提交 git log --author="author" # 查看某个作者的提交记录 git log --committer="committer" # 查看某个提交者的提交记录 git log --grep="keyword" # 搜索提交说明中的关键字 git log -S content-keyword # 搜索提交内容中含有 keyword 的提交 git show <commit> # 查看提交内容
-
撤销操作
git reset --hard README.md # 取消暂存 README.md 文件 git checkout -- README.md # 将 README.md 文件恢复到上次提交的状态 git reset --soft HEAD~1 # 撤销上一条提交,并保留修改的文件
-
回滚
git reset --hard <commit0> # 直接从当前提交(commit3)回滚到指定提交(commit0), 中间提交都无了(commit3/2/1) git revert --hard <commit0> # 撤销指定提交的 commit, 会把 commit0 的提交从现在的 git 流里删除, 可能需要解决冲突
-
远程仓库
git clone <url> # 获取远程仓库 git remote -v # 查看远程仓库简写和其对应的路径 git remote add <shortname> <url> # 添加远程仓库 git remote show <remote> # 展示仓库的相关信息(地址/当前分支/远程分支状态/本地分支) git fetch <remote> # 拉取远程更新(需要手动合并) git push <remote> <branch> # 推送到远程分支 git pull <origin> <branch> # 拉取指定分支的远程引用, 并合并到本地分支 git remote rename <oldName> <newName> # 重命名仓库简称 git remote remove <remote> # 删除远程仓库
-
标签
轻量标签
相当于某个提交的应用, 只附带当前提交信息.
附注标签
附注标签是存储在 Git 数据库中的一个完成对象, 它是可以被校验的, 其中包含打标签者的名字、电子邮件、地址、日期时间, 此外还有一个标签信息, 能够用 GPG 签名并验证.
git tag # 展示已有标签 git tag -l "v1.1.*" # 检索标签 v1.1.1, v1.1.2 git tag -a "v1.0" -m "this is v1.0" # -a 创建一个附注标签 -m 为标签添加描述 git show v1.4 # 查看标签信息和对应的提交信息 git tag v1.0 # 创建一个轻量标签 不需要使用 -a、-s 或 -m 选项, 只需要提供标签名字 git tag -a v1.2 <commit-hash> # 为提交补上标签 git push <remote> <tagname> # 将标签推送到远程仓库 git push <remote> --tags # 将所有不在远程仓库的标签全部推送上去 git tag -d v1.2 # 删除本地标签 git push origin --delete <tagname> # 删除远程仓库标签 # 检出标签文件版本 git checkout -b <new-branch> # 创建并切到换新分支 git checkout -b <new-branch> <commit/branch> # 创建并切到换新分支, 同时制定开始的提交/分支 git checkout v1.2 # 检出 v1.2 的提交 git chekcout -b <new-branch> <tagname/remote-branch> # 创建新分支, head 为 tag/remote-branch 的 commit
-
GIt 别名
git config --global alias.unstage 'reset HEAD --' git unstage fileA # == git reset HEAD -- fileA
-
HEAD、HEAD~、HEAD^ 说明
HEAD: 指向当前所在分支的最新提交
HEAD~{n}: 指向当前路径的第 n 个提交
HEAD = HEAD~0
HEAD~ = HEAD~1
HEAD~~ = HEAD~2
HEAD^n: 切换父级提交路径的第 n 个提交(父级本身就代表了回溯了 1 次)
# 当前提交 HEAD = HEAD~0 = HEAD^0 # 主线回溯 HEAD~1 = HEAD^ 主线的上一次提交 HEAD~2 = HEAD^^ 主线的上二次提交 HEAD~3 = HEAD^^^ 主线的上三次提交 # 如果某个节点有其他分支并入 HEAD^1 主线提交(第一个父提交) HEAD^2 切换到了第2个并入的分支并得到最近一次的提交 HEAD^2~3 切换到了第2个并入的分支并得到最近第 4 次的提交 HEAD^3~2 切换到了第3个并入的分支并得到最近第 3 次的提交 # ^{n} 和 ^ 重复 n 次的区别 HEAD~1 = HEAD^ HEAD~2 = HEAD^^ HEAD~3 = HEAD^^^ # 切换父级 HEAD^1~3 = HEAD~4 HEAD^2~3 = HEAD^2^^^ HEAD^3~3 = HEAD^3^^^
-
分支
git branch # 查看本地分支 git branch -r # 查看远程分支 git branch -v # 查看本地分支及其最后的提交描述 git branch <branch-name> # 创建分支 git checkout <branch-name> # 切换分支 git checkout -b <branch-name> # 创建分支并切换 git branch -d <branch-name> # 删除本地分支 git branch -D <branch-name> # 强制删除本地分支(被删除分支未被合并或推送) git push <remote> --delete <branch-name> # 删除远程分支 git branch --set-upstream-to <remote/branch-name> # 本地分支关联远程分支 git push --set-upstream-to <remote> <branch-name> # 推送本地分支到远程 git merge <branch-name> # 合并指定分支到当前当前分支 git branch -m <old-name> <new-name> # 分支重命名
冲突说明
<<<<<<< HEAD:index.html <div id="footer">contact : email.support@github.com</div> ======= <div id="footer"> please contact us at support@github.com </div> >>>>>>> iss53:index.html
=== 上半部分表示 HEAD 所指示的版本(当前分支).
=== 下半部分表示需要合并的版本(希望合并的分支).
解决冲突后(删除 <<< / === / >>>), 使用
git add
来将其标记为冲突已解决. -
.gitignore
-
submodule
git submodule add <repository-url> # 添加子模块 git config submodule.<repository>.url <url> # 设置子模块 url git log --submodule # 查看子模块相关的提交记录 git submodule sync --recursive # 修改 .gitmodule 的子模块 url 后, 同步配置到子模块内的 remote 上
clone 包含子模块的仓库流程
# 方式1 git clone <repository-url> # clone 父项目 cd <submodule-name> # 进入子模块目录, ls 后发现为空 git submodule init # 初始化子模块仓库 git submodule update # 拉取父项目中的合适的提交 # 方式2 git submodule update --init # 初始化并更新子模块 git submodule update --init --recursive # 递归更新子模块内的子模块 # 方式3 git clone --recurse-submodules <repository-url> # clone 父项目的同时自动初始化并更新子模块
更新仓库内的子模块
# 方式 1 cd <submodule> # 进入子模块 git pull # 拉取更新 git diff --submodule # 查看子模块更新的 commit git pull --recurse-submodules # 拉取更新(包括子模块内的子模块) # 方式 2 git submodule update --remote <submodule> # 更新子模块 git config --global diff.submodule log # 设置 git diff 默认行为
删除仓库内的子模块
-
Delete the relevant section from the
.gitmodules
file. -
Stage the
.gitmodules
changes:git add .gitmodules
-
Delete the relevant section from
.git/config
. -
Remove the submodule files from the working tree and index:
git rm --cached path_to_submodule
(no trailing slash). -
Remove the submodule’s
.git
directory:rm -rf .git/modules/path_to_submodule
-
Commit the changes:
git commit -m "Removed submodule "
-
Delete the now untracked submodule files:
rm -rf path_to_submodule
-