对于某些命令的详细用法,如果本页写的不详细
- 查看详细介绍
- 搜索其他资料
- 留言我来补充
其他资料
Git 操作往往会遇到各种问题,比如,如何把未暂存的内容移动到一个新分支,或者删除的分支如何恢复。这个仓库就收集这类问题的操作方法
搞清楚每一个命令是什么用途,或者在 测试仓库中测试后再用于项目中
https://github.com/k88hudson/git-flight-rules/blob/master/README_zh-CN.md
暂存文件
暂存指定文件的更改
想暂存某些具体的文件
# -- 意为后边跟的是路径;可以省略;在某些场景下省略会出错$ git add -- index.js index.css
批量暂存更改
想要一次性将所有文件暂存
# 所有更改的文件$ git add .$ git add *# 任意目录下 js 文件$ git add **/*.js
暂存某个文件的部分内容
一不小心在一个文件中添加了两块功能的代码,但是想按照功能提交修改。
解决方法:
- 使用 SourceTree 的暂存块、暂存行功能
git add -p
操作 Commit
只提交部分文件
一不小心执行了 git add . 暂存了所有文件,但我们只需要给部分文件做提交
# 1. 直接 commit 指定文件路径# git commit <option> [--] <pathspec>$ git commit -m 'msg' -- **/*.js # 任意路径下的任意 js 文件$ git commit **/*.js -m "msg"# 2. 使用 git reset 撤销; 已暂存的文件取消暂存,重新放在工作区# 默认是 HEAD ;所以 HEAD 可省略$ git reset [HEAD] <filePath>
修改最新提交信息
修改 commit 的 msg
修补式提交 - 修补提交命令 --amend
# 1. 进入 vim 修改信息,保存git commit --amend# 2. 使用 reset 命令# 将 HEAD 指针指向上一次提交,暂存区和工作区不变(保持当前状态)# 使用 .git/COMMIT_EDITMSG(也就是上一次 commit 使用) 的信息重新提交$ git reset --soft HEAD^ && git commit -e -F .git/COMMIT_EDITMSG
修改老旧 commit msg
# 变基(base):-i 采用交互式方式# 在出来的交互界面 选择当前要修改的 commit,改为 r(重新编写)$ git rebase -i <被变的 commit 的父亲># 或者$ git rebase -i <commit-id>^...Successfully rebase and update refs/heads/master
注意:编辑修改历史 commit 是对自己本地的分支进行修改;如果对已经推送到远程集成分支上,则不要轻易修改,否则会给小伙伴们造成不必要的麻烦
实操
====================
修改倒数第三个 commit 信息
查看当前的 commit 信息历史
执行 git rebase ca7cece
修改“去除空格”的 pcik -> <r | reword> 
进入 rebase 的交互界面 - 1

进入 rebase 的交互界面 - 2
重新修改目标 commit;并 :wq 保存退出

修改成功 对比修改前后的 commit 变化
修改了 历史 commit 后,自父亲之下所有的 commit 都会变化
blob 对象只看文件内容是否变化,如果两个文件相同,blob 就相同,即使是在不同的仓库中。 但 commit 对象包括树对象、父提交、作者、提交者、msg、变更时间等属性,任何一个属性值变化,在 git 中,就是不同的 commit。
$ git cat-file -p newMaster tree 3544e61e812c47a2e0477fc218569fb4ad3da0d9 parent 762da6042475cc0d4183eedbcbedd02b9fe7caee author YiBu tiandaochouqinyn@163.com 1568129498 +0800 committer YiBu tiandaochouqinyn@163.com 1568129498 +0800 new master 新行
合并多个 Commit
场景
===
一开始连续创建了许多 commit,过了段时间发现,这几个 commit 就是一个功能,需要合并 commit 以保证分支历史的简洁、清晰。
整理过去创建的 commit 的场景。
TODO:合并 commit 的过程中可能会有冲突,此种情况待测试
如何合并到第一个提交
当使用 git reset <commitId> 要合并到第一个提交时,vim 界面不会出现第一个提交,此时可以手动添加不存在的提交信息
合并连续的 commit 为一个
# 1. 合并最近的两个提交 -> 为一个$ git reset --soft HEAD^^$ git commit -m "msg"# 2. 合并到 <commit-id> 的提交(但是不包括当前 commit-id)git rebase -i <commit-id># 合并前两条的 commit 信息$ git rebase -i HEAD~2pick 5e130d9 添加 b 函数pick bc4e0d5 askdkajdkasjdkajdka几节课# Rebase f6687e6..bc4e0d5 onto f6687e6 (2 commands)## Commands:# p, pick = use commit# r, reword = use commit, but edit the commit message# e, edit = use commit, but stop for amending# squash = 使用这个 commit,但是要融合进前一个 commit# 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 rebash -i dd10 准备合并前四个 commit
将要合并的 commit 标识改为 s 或者 squash(挤压、压入)
上一步保存后,出现编辑 commit 信息界面:为什么做此次变更# 标识的为注释,不出现在 msg 中。
保存后查看 分支信息 git log --graph --oneline --all 
使用 git reflog 查看合并过程执行了那些操作
合并间隔 commit 为一个
利用 git rebase -i 进入 vim 交互界面,调整间隔 commit 顺序后,再合并 commit
查看提交历史
执行 git rebase -i 1f40772 
调整 commit 顺序,并合并 commit。
(如果缺少 commit-id,只要补充对应的 commands 和 commit-id 就可以整合 commit;适用于合并根提交情况)


拆分已提交的 Commit
松耦合
# 1. 将当前提交撤销,重置为上一次提交。将撤销的提交的改动保存在工作区内$ git reset HEAD^# 2. 通过补丁块拣选方式选择要提交的修改。Git 会逐一显示工作区更改$ git add -p# 3. 以撤销提交的提交说明为蓝本,撰写新的提交# -C 重新使用特定的 commit 信息# -c 重新使用并编辑特定的 commit 信息# -e 强制编辑 commit 信息$ git commit -e -C HEAD^# 对工作区的其余修改进行提交,完成一个提交拆分两个的操作$ git add -u$ git commit
TODO:紧耦合
要拆分的提交,不同的实现逻辑耦合在一起,难以通过拣选的方式修改
TODO:拆分历史某个提交
# 1、执行 rebase$ git rebase -i HEAD~3# 2、修改目标提交的操作命令;# 将需要拆分的 commit 的 pick 修改为 editedit commit1pick commit2pick commit3# 3、将暂存区与 HEAD 的文件重置为上一次状态;类似文件修改但未执行 git add 前的状态$ git reset HEAD^# 4、挑选需要提交的内容,进行提交。如git add change1.cppgit commit -m "Version 1-A"git add change2.cppgit commit -m "Version 1-B"# 5、完成后续 rebase 过程$ git rebase --continue
发现提交的 commit 少提交或误提交一部分文件或内容
单步悔棋
# 处理误提交的内容## 第一步:## 如果是少提交内容:将其添加到暂存区$ git add <少提交的内容>## 如果是提交了不该提交的东西:先将暂存区和工作区的文件恢复$ git checkout HEAD^ -- <fileName>## 第二步:## 修补式提交:重新编写提交信息$ git commit --amend -m "msg"## 或者:在上一次的 msg 基础上修改$ git commit -e -F .git/COMMIT_EDITMSG
重置用户信息:提交作者
发现项目的用户配置信息错误,需要纠正
# 1、修改项目的用户信息$ git config --local user.name 'name'$ git config --local user.email 'XXX@XXX'# 2、重置上次信息可以配合 git rebase 修改历史提交的作者信息# 3、替换“拆分历史提交”的第 4 步操作$ git rebase -i <commit^>## 修改目标 <commit> pick 为 edit,保存退出编辑界面# 4、这个命令会更改提交时间$ git commit --amend --reset-author$ git rebase --continue# 4、只修改作者信息## -C 创建提交时使用指定的提交对象的日志消息、作者信息、时间戳$ git commit --author "Name <name@163.com>" --amend --no-edit -C HEAD$ git rebase --continue
官方文档:changing author info~~ ~~
官方地址:changing author info
新建一个裸仓库,以直接修改仓库里信息的方式修改作者,将分支推送到远程
博客:修改git commit的author信息
会更改 commit 的时间
Git Pro: Git Tool Rewriting History
中文版:重写历史
查看 commit 历史、提交日志
# 查看所有分支的前 8 个日志,以图形方式显示$ git log -n8 --graph --all
文件、版本之间差异
比较暂存区和 HEAD 文件差异
index 暂存区
HEAD 版本库当前版本
$ git diff --cached [HEAD]$ git diff --staged [HEAD]
比较工作区和暂存区文件差异
$ git diff
比较不同分支或提交之间的差异
# commit-id 可以为 commit-id 、分支名、tag 等$ git diff <commit-id-1> <commit-id-2># 查看不同提交之间指定文件差异$ git diff <C1> <C2> -- <filePaths>
查看不同提交之间文件变化统计信息
# 统计提交之间那些文件发生了变化$ git diff --statfile1 | 2 ++filw2 | 2 ++2 files changed, 4 insertions(+), 2 deletions(-)# 详细增减行数统计以及文件路径$ git diff --numstat2 0 file12 0 filw2# 只显示文件路径$ git diff --name-only
查看某次提交后,所有变动的文件
场景:修改一些列 Bug 后,部署到服务器(只部署修改的文件)
# 不包含 commitId 中的文件,如要包含可使用 commitId^$ git diff --name-only <commitId>
文件、版本控制
暂存区恢复成 HEAD 一样
# 如果只需要操作部分文件,在命令后边加 -- <filePaths># 1. 保留暂存区更改$ git commit ...# 2. 丢弃暂存区更改# 重置暂存区为 HEAD 版本,但是工作区不变# -mixed -- reset the index but not the working tree (default)$ git reset [--mixed] HEAD
取消暂存区部分文件的更改
$ git reset HEAD -- <fileNames>
让工作区恢复为与暂存区一样
# 如果只需要操作部分文件,在命令后边加 -- <filePaths># 1. 保留工作区更改$ git add <filePath># 2. 丢弃工作区更改## 危险操作,一旦执行,修改将找不回来$ git checkout -- <filePath>
消除最近几次提交 | 版本回退
# commit-id 可以通过 Git log 查询;也可以通过 git reflog 查询## 危险操作,会丢弃 commit-id 后的版本;并且工作区和暂存区的修改也将丢弃,变为 commit-id 指定内容。$ git reset --hard <commit-id>
删除文件的方式
# 彻底删除文件:本地以及版本库都不需要## 方法 1:$ rm <file> && git add <file>## 方法 2:$ git rm <file># 本地依然需要,但是不需要让 Git 管理了## 如,不小心将 dist/*、 node_model/* 加入版版本控制$ git rm --cached <file>
临时加塞紧急任务如何处理
场景描述
===
临时加塞紧急任务,但是功能没完成不想单独生成一个 commit
stash 恢复的文件会直接覆盖工作区
# 贮藏当前所有的变更(保存当前工作进度)$ git stash# 列出当前所有的 Stashing$ git stash list# 恢复 stash@{0} 的 Stashing$ git stash apply stash@{0}# 删除已经恢复的 Stashing$ git stash drop
指定不需要管理的文件
如:程序构建出的中间文件或暂存文件或私密文件
忽略规则只对尚未 track 的文件有效,如果已经被追踪过了需要清除
$ git rm -r --cached [path]
文件可以放在任何目录,起作用范围对其所处目录及子目录有效
# .gitignore# 基本符合 glob 规则
由于 git 只管理文件,所以对于空文件夹是不做追踪的
解决:在空文件夹中新建一个文件,通常使用 .gitkeep
分支操作
Git 会把每次提交依据时间连成一条线,这条提交线就是分支。
新建分支时,Git 创建一个指针如 dev ,指向 master 相同的提交,并且 HEAD 头指针 指向新分支 dev
新建分支
# 新建分支并切换到新分支$ git checkout -b <newBranch># 只新建分支不切换$ git branch <newBranch># 以某个 commit-id(即 start-point) 为基准新建分支## commit-id: 指某个本地分支、远程分支、或具体的 commit$ git checkout <commit-id> -b <newBranch>$ git branch <commit-id> <newBranch>## 或者$ git checkout -b <newBranch> <commit-id>$ git branch <newBranch> <commit-id>
基于远程分支新建本地分支
# 远程存在的分支,本地没有此分支## 会新建同名本地分支,并设置追踪关系$ git checkout --track origin/branch-name# 通用命令:如果本地没有对 origin/branch-name 的引用,需要先 git fetch## 既可以新建同名又可以修改名字建分支$ git checkout -b branch-name origin/branch-name
分支切换
$ git checkout <branch>
分支切换可能不会成功,因为当工作区对某些文件做了修改但是没有提交后,git 会阻止进行分支切换。此时可以后三种处理方式
- 放弃修改所有修改
git checkout -- . - 提交一个 commit
git add . && git commit -m "msg" - 保存工作进度
git stash
删除不常用的分支
# bn 为分支名# 当没有分支有新的提交,并且没有完全合并入其他分支时,会警告$ git branch -d bnerror: The branch 'bn' is not fully merged.if you are sure you want to delete it, run "git brnach -D bn".# 强制删除分支$ git branch -D <branch># 删除远程分支$ git push origin --delete <远程分支># 删除远程分支 === 推送一个空分支$ git push origin :<远程分支>
分支修改
# 修改分支名称$ git branch -m <oldBranch> <newBranch>fatal: A branch named 'master' already exists.# 强制修改分支名称$ git branch -M <oldBranch> <newBranch># 本地分支与远程分支关联$ git branch --set-upstream-to <branch-name> origin/<branch-name>
分支集成策略
远程操作
clone 克隆
从远程指定的分支克隆
$ git clone <url> -b dev
remote 远程主机操作
# 查看所有远程主机地址详情$ git remote -vorigin <xxx 仓库网址> (fetch)origin <xxx 仓库网址> (push)# 列出所有远程主机$ git remote showorigin# 查看某一个远程主机详细信息$ git remote show origin# 添加一个远程主机$ git remote add <主机名> <网址># 删除远程主机$ git remote rm <主机名># 重命名远程主机$ git remote rename <原主机名> <新主机名>
Fetch 拉取远程更新
# 拉取某个主机上的全部更新$ git fetch <远程主机名># 只取特定分支跟新$ git fetch origin master
Pull 获取更新并合并
# 获取远程分支更新并合并到当前分支$ git pull origin master# 建立分支之间的追踪关系$ git branch --set-upstream master origin/next# 建立追踪关系后:默认从当前分支对应的远程分支上拉取合并$ git pull
可能产生冲突的场景
不同的人修改了不同文件
合并顺利,没有冲突。注意防止逻辑冲突
不同人修改了的同文件的不同区域
会自动合并
不同人修改了同文件的同一区域
直接冲突
同时变更了文件名和文件内容
可以感知到文件名变更;自动合并
