作为一个非常有历(wei)史(dao)的 版本控制系统 ,Git 理所当然地存在很多历史遗留问题。然而我们不想解决历史遗留问题——它们实在是太多了。 所以,你应该学会叫 Git 这个 git(饭桶)闭嘴;至少,不要叫那些历史遗留的 s@#t 来污染你的大脑。
如果你不能理解本文的内容,照着做就是了;如果你连照着做也做不到,就不要用 Git。
Git 有时候需要你使用 文本编辑器 ,例如使用 git commit
的时候它会提示你输入提交注释,你使用 git rebase -i
的时候它会将即将执行的命令的清单显示给你并且你可能会对其进行修改。那个叫 vim 的 不配 被称为文本编辑器。我们推荐使用 GNU nano。如果你在用 Windows,可以试试 这个。
在你能好好地使用 Git 管理你的代码之前,把这几个设置改一下:
$ git config --global color.status auto # 使 git status -s 命令的输出带有颜色。
$ git config --global color.diff auto # 使 git diff 命令的输出带有颜色。
$ git config --global color.branch auto # 使 git branch -a 命令的输出带有颜色。
$ git config --global color.interactive true # 使 git add -i 命令的输出带有颜色。
$ git config --global core.editor /usr/bin/nano # 请不要理会那个竟然敢自称编辑器的叫 vi 的智障。
$ git config --global core.pager "less -x1,5" # 设置好 diff 的对齐。 [1]
$ git config --global core.autocrlf input # 别把 CR LF 提交到服务器上。
$ git config --global push.default simple # 仅 push 当前分支。
$ git config --global pull.ff only # 禁用非 --ff-only 的 pull 操作。
$ git config --global merge.ff only # 禁用非 --ff-only 的 merge 操作。
[1] http://lists.gnu.org/archive/html/nano-devel/2017-12/msg00117.html
《Git 工作流程》
http://www.ruanyifeng.com/blog/2015/12/git-workflow.html
仅参考其中的 Gitlab flow。
master 分支(debug/unstable)仅作开发,产品分支(release/stable)仅以 cherry-pick 更新。
《常用 Git 命令清单》
http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html
《Git 使用规范流程》
http://www.ruanyifeng.com/blog/2015/08/git-use-process.html
--ff-only
除外。--ff-only
和 --rebase
除外。$ git checkout master
$ git fetch
$ git reset --hard origin/master
$ git checkout -b working
$ git add 第一个文件
$ git add 第二个文件
$ git commit
$ git push origin working
$ git checkout master
$ git pull --ff-only
$ git branch -d working
$ git push origin :working
$ git fetch
$ git rebase origin/master
$ git status -s
M 暂存区 变基并且没有冲突的文件
M 工作区 修改但是没有提交的文件
?? 非追踪 没有加入版本控制的文件
UU 冲突 变基出现冲突的文件
<<<<<<<
(7 个)标记并进行编辑,保存为要保留的内容,然后标记为 已解决 :$ git add 变基出现冲突的文件
--ours
是 基点 ):$ git checkout --ours 变基出现冲突的文件
$ git add 变基出现冲突的文件
--theirs
是 本地 ):$ git checkout --theirs 变基出现冲突的文件
$ git add 变基出现冲突的文件
$ git rebase --continue
$ git push origin +working
$ git rebase --abort
(以下假定下游远端为 origin,上游远端为 upstream,双方的主分支都是 master。)
$ git fetch upstream
$ git checkout -b rebasing
$ git rebase upstream/master
$ git checkout -B master
$ git push origin +master
$ git format-patch upstream/master
应用补丁文件:
$ git am 第一个补丁文件 第二个补丁文件
推送到远端分支
$ git push
挑拣单个提交:
$ git cherry-pick 单个提交散列标识
推送到远端分支
$ git push
为了降低入门难度,这部分参考的内容是按照 常用操作 而不是按照命令排序的。由于 Git 命令被 极其糟糕 地重载, 去读他喵的手册(RTFM) 虽然是正统且全面的指南,但是被认为不能帮助新手很快地投入日常使用。
本文中所有的 术语(term) 皆以 斜体字 标出。术语 的含义是 明确的、 严格的、 不可替代的。在 术语 首次出现时,它会被标明对应的英文原文。
<>
表示必需参数,方括号 []
表示可选参数。[--]
用于分隔文件路径和参数。不过,一般情况下不需要这个分隔符,除非文件名以 -
开头使得它看来像一个参数。当此分隔符为必需时,将额外说明。...
表明前面邻接的参数可以有多个。克隆到和仓库同名的文件夹:
git clone <仓库地址>
克隆到指定的文件夹:
git clone <仓库地址> [--] <目标文件夹>
添加文件或一个文件夹下的所有未被忽略的文件:
git add [--] <待添加的文件或文件夹>...
强制添加已被忽略的文件或文件夹:
git add -f [--] <待添加的文件或文件夹>...
git add
操作撤销文件或文件夹下的所有文件(方法一):
git reset [--] <待撤销的文件或文件夹>...
撤销文件或文件夹下的所有文件(方法二):
git rm --cached [--] <待撤销的文件>...
git rm --cached -r [--] <待撤销的文件夹>...
创建新的 提交(commit),打开文本编辑器书写提交日志:
git commit
创建新的 提交,直接在命令行上写入提交日志:
git commit -m <提交日志>
修改最后一次 提交,打开文本编辑器书写提交日志:
git commit --amend
修改最后一次 提交,直接在命令行上写入提交日志:
git commit --amend -m <提交日志>
打开文本编辑器书写提交日志(如果待提交的文件或文件夹已经从文件系统删除,就必须使用 --
来标示路径):
git commit [--] <待提交的文件或文件夹>...
直接在命令行上写入提交日志(如果待提交的文件或文件夹已经从文件系统删除,就必须使用 --
来标示路径):
git commit -m <提交日志> [--] <待提交的文件或文件夹>...
修改最后一次 提交,打开文本编辑器书写提交日志(如果待提交的文件或文件夹已经从文件系统删除,就必须使用 --
来标示路径):
git commit --amend [--] <待提交的文件或文件夹>...
修改最后一次 提交,直接在命令行上写入提交日志(如果待提交的文件或文件夹已经从文件系统删除,就必须使用 --
来标示路径):
git commit --amend -m <提交日志> [--] <待提交的文件或文件夹>...
移除文件或文件夹并删除它,如果有未提交的修改则该操作失败:
git rm [--] <待移除的文件>...
git rm -r [--] <待移除的文件夹>...
移除文件或文件夹并删除它,如果有未提交的修改则丢弃之:
git rm -f [--] <待移除的文件>...
git rm -fr [--] <待移除的文件夹>...
git commit
操作撤销提交,被提交的修改进入 工作区:
git reset HEAD~1
撤销提交,被提交的修改进入 暂存区:
git reset --soft HEAD~1
撤销提交,丢弃已提交的修改:
git reset --hard HEAD~1
将文件或文件夹的修改还原至 暂存区 的状态:
git checkout [--] <待还原的文件或文件夹>...
将文件或文件夹的修改还原至最后一次提交的状态:
git checkout HEAD [--] <待还原的文件或文件夹>...
将文件或文件夹的修改还原至上一次提交的状态:
git checkout HEAD~1 [--] <待还原的文件或文件夹>...
将文件或文件夹的修改还原至其他分支的状态:
git checkout <源分支> [--] <待还原的文件或文件夹>...
丢弃 工作区 的所有修改:
git checkout -- :/
丢弃 暂存区 和 工作区 的所有修改(方法一):
git checkout HEAD -- :/
丢弃 暂存区 和 工作区 的所有修改(方法二):
git checkout -f
丢弃 暂存区 和 工作区 的所有修改(方法三):
git reset --hard
使用 工作区 的文件来解决冲突:
git add <冲突的文件>...
删除指定的文件来解决冲突:
git rm --force <冲突的文件>...
从其他分支提取文件或文件夹进入 暂存区(如果文件参数是当前文件系统中不存在的文件,就必须使用 --
来标示路径):
git checkout <源分支> [--] <待提取的文件或文件夹>
提取发生 冲突 的文件的对应当前分支(对于 git merge
)或目标分支(对于 git rebase
)上的文件或文件夹进入 工作区,保留冲突状态:
git checkout --ours [--] <待提取的文件或文件夹>
提取发生 冲突 的文件的对应目标分支(对于 git merge
)或当前分支(对于 git rebase
)上的文件或文件夹进入 工作区,保留冲突状态:
git checkout --theirs [--] <待提取的文件或文件夹>
删除 工作区 中当前目录下的所有未被跟踪的文件和文件夹,包括已忽略的:
git clean -fdx
删除 工作区 中当前目录下的所有未被跟踪的文件和文件夹,除了已忽略的:
git clean -fd
删除 工作区 中当前目录下的所有已忽略的文件和文件夹:
git clean -fdX
查看 暂存区 和 工作区 的所有文件状态:
git status -s
M 已向暂存区添加
D 已从暂存区删除
M 已在工作区修改
D 已从工作区删除
UU 冲突
?? 未跟踪
查看 本地分支(local branch):
git branch
查看 本地分支(local branch) 和 远端分支(remote branch):
git branch -a
master 本地分支 master
remotes/origin/master 远端分支 origin/master (对应 origin 远端上的 master 分支)
remotes/upstream/temp 远端分支 upstream/temp (对应 upstream 远端上的 temp 分支)
切换到指定的分支:
git checkout <目标分支>
切换到上一次切换以前的分支:
git checkout -
创建一个和当前分支一样的分支并保持当前分支不变,如果新分支已存在则该操作失败:
git branch <新分支>
创建一个和当前分支一样的分支并切换到新分支,如果新分支已存在则该操作失败:
git checkout -b <新分支>
创建一个和当前分支一样的分支并切换到新分支,如果新分支已存在则覆盖之:
git checkout -B <新分支>
删除 本地分支,如果分支未被 合并(merge) 到 上游分支(upstream branch) 则该操作失败:
git branch -d <旧分支>
删除 本地分支,不检查合并状态:
git branch -D <旧分支>
重命名 本地分支:
git branch -m <旧分支> <新分支>
更新当前分支的 上游分支 的 远端 上的所有分支到本地的 远端分支:
git fetch
更新指定 远端 上的所有分支到本地的 远端分支:
git fetch <远端>
更新所有 远端 上的所有分支到本地的 远端分支:
git fetch --all <远端>
将其它分支 合并(merge) 到当前分支(创建合并节点,当前分支变为该节点的子分支):
git merge <目标分支>...
将另一条分支 合并 到当前分支,如果目标分支不是当前分支的子分支则该操作失败:
git merge --ff-only <目标分支>
将当前分支 变基(rebase) 到另一条分支(将两条分支不同部分切除,然后拼接在目标分支之后,结果保存为当前分支):
git rebase <目标分支>
复制另一条分支到当前分支:
git reset --hard <目标分支>
更新当前分支的 上游分支 的 远端 上的所有分支到本地的 远端分支,再使用 git merge
更新 本地分支:
git pull
更新当前分支的 上游分支 的 远端 上的所有分支到本地的 远端分支,再使用 git merge --ff-only
更新 本地分支:
git pull --ff-only
更新当前分支的 上游分支 的 远端 上的所有分支到本地的 远端分支,再使用 git rebase
更新 本地分支:
git pull --rebase
更新当前分支到其 上游分支:
git push
更新指定的 本地分支 到指定 远端 上的 上游分支,如果 本地分支 没有 上游分支 则该操作失败:
git push <远端> <本地分支>
更新指定的 本地分支 到指定 远端 上的 上游分支,如果 本地分支 没有 上游分支 则使用同名的分支作为 上游分支 并设置之:
git push -u <远端> <本地分支>
更新当前分支到指定 远端 上的指定分支:
git push -u <远端> HEAD:<分支>
更新指定的 本地分支 到指定 远端 上的指定分支:
git push -u <远端> <本地分支>:<分支>
删除指定 远端 上的指定分支:
git push -u <远端> :<分支>