以下内容是我在学习和研究Git时,对Git操作的特性、重点和注意事项的提取、精练和总结,可以做为Git操作的字典,方便大家查阅;
备注:本文会不断更新完善;
目录
一. 语法格式描述
二. git环境变量存放的3个位置
三. 配置
1. 用户信息
2. 查看配置信息
3. 文本编辑器
4. 差异分析工具
四. 获取帮助
五. Git常用命令
1. 获得项目的Git仓库
2. 添加跟踪文件、暂存
3. 检查当前文件状态
4. 忽略某些文件
5. 查看已暂存和未暂存的更新
6. 提交更新
7. 移除文件
8. 移除文件
9. 查看提交历史
10. 撤消操作
11. 远程仓库
12. 标签
13. 新建分支
14. 切换分支
15. 新建并切换分支
16. 合并分支
17. 删除分支
18. 强制删除分支
19. 查看当前分支列表
20. 查看各个分支最后一次提交对象的信息
21. 查看已经合并到当前所在分支的分支
22. 查看未合并到当前所在分支的分支
23. 跟踪远程分支
24. 删除远程分支
25. 分支的衍合
六. 分支、HEAD、ref的区别
七. 远程分支、远程跟踪分支、跟踪分支的区别
八. 命令详解
1. 克隆clone
2. 远程remote
3. 获取fetch
4. 拉取pull
5. 分支branch
6. 提交commit
7. 推送push
九. Git问题解决方案
1. 不显示中文
2. 添加远程跟踪分支
3. 把本地项目推送到新的远程仓库
4. 彻底删除文件或目录
内容
一. 语法格式描述
本文采用BNF语法格式描述规范描述命令行的语法,BNF语法格式的元字符及其含义如下:
[ ]
:可选内容;
< >
:必须给出内容;
{ }
:可重复0至无数次的内容;
a|b|c
:多选一;
…
:可以有多个;
备注:关于BNF的详细内容可参考《语法格式描述规范BNF和ABNF》
二. git环境变量存放的3个位置
-
/etc/gitconfig
文件:系统中对所有用户都普遍适用的配置。若使用git config
时用--system
选项,读写的就是这个文件。 -
~/.gitconfig
文件:用户目录下的配置文件只适用于该用户。若使用git config
时用--global
选项,读写的就是这个文件。 - 当前项目的 git 目录中的配置文件(也就是工作目录中的
.git/config
文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以.git/config
里的配置会覆盖/etc/gitconfig
中的同名变量。
三. 配置
1. 用户信息
$ git config --global user.name "John Doe"
$ git config --global user.email [email protected]
如果用了 --global
选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。如果要在某个特定的项目中使用其他名字或者电邮,只要去掉 --global
选项重新配置即可,新的设定保存在当前项目的 .git/config
文件里。
2. 查看配置信息
git config --list
有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig
和 ~/.gitconfig
),不过最终 Git 实际采用的是最后一个
也可以直接查阅某个环境变量的设定,只要把特定的名字跟在后面即可,像这样:
$ git config user.name Scott Chacon
3. 文本编辑器
Git 需要你输入一些额外消息的时候,会自动调用一个外部文本编辑器给你用。默认会使用操作系统指定的默认编辑器,一般可能会是 Vi 或者 Vim。如果你有其他偏好,比如 Emacs 的话,可以重新设置:
$ git config --global core.editor emacs
4. 差异分析工具
在解决合并冲突时使用哪种差异分析工具。比如要改用 vimdiff 的话:
$ git config --global merge.tool vimdiff
Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合并工具的输出信息。当然,你也可以指定使用自己开发的工具;
四. 获取帮助
想了解 Git 的各式工具该怎么用,可以阅读它们的使用帮助,方法有三:
git [命令] --help
$ man git
比如,要学习 config 命令可以怎么用,运行:
$ git help config
五. Git常用命令
1. 获得项目的Git仓库
有2种获得 Git 项目仓库的方法:
- 通过Git的init命令初始化一个新仓库;
- 通过Git的clone命令从已有的 Git 仓库(可以是本地的,也可以是远程的)克隆出一个新的镜像仓库来。
1.1 在工作目录中初始化新仓库
要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行:
$ git init
1.2 从现有仓库克隆
命令格式:
$ git clone [url]
比如,要克隆 Ruby 语言的 Git 代码仓库 Grit,可以用下面的命令:
$ git clone git://github.com/schacon/grit.git
如果希望在克隆的时候,自己定义要新建的项目目录名称,可以在上面的命令末尾指定新的名字:
$ git clone git://github.com/schacon/grit.git mygrit
如果希望克隆时直检出指定的分支,可以指定 -b <分支名>
选项,如下:
$ git clone -b Tool https://gitee.com/guobinyong/Opus.git 工具
通常clone命令会把整个仓库的(包含所有分支的)版本数据给克隆下来,如果只想获取某个分支的版本数据,只需要加上 --single-branch
选项,如下:
$ git clone --single-branch -b Tool https://gitee.com/guobinyong/Opus.git 工具
2. 添加跟踪文件、暂存
$ git add 文件名
这是个多功能命令,根据目标文件的状态不同,此命令的效果也不同:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等;
其实 git add
的潜台词就是把目标文件快照放入暂存区域,也就是 add file into staged area,同时未曾跟踪过的文件标记为需要跟踪。
3. 检查当前文件状态
$ git status
4. 忽略某些文件
创建一个名为 .gitignore 的文件,列出要忽略的文件模式;
比如:
$ cat .gitignore *.[oa] *~
文件 .gitignore 的格式规范如下:
- 所有空行或者以注释符号 # 开头的行都会被 Git 忽略。
- 在一行的末尾添加注释,会使该行被Git忽略,所以注释只能独占一行,不能添加在行的末尾;
- 可以使用标准的 glob 模式匹配。
- 匹配模式最后跟反斜杠(/)说明要忽略的是目录。
- 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。
.gitignore 文件的例子:
# 此为注释 – 将被 Git 忽略
# 忽略所有 .a 结尾的文件
*.a
# 但 lib.a 除外
!lib.a
# 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
/TODO
# 忽略 build/ 目录下的所有文件
build/
# 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
doc/*.txt
5. 查看已暂存和未暂存的更新
$ git diff
此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。
若要看已经暂存起来的文件和上次提交时的快照之间的差异,可以用 git diff --cached
命令。(Git 1.6.1 及更高版本还允许使用 git diff --staged
,效果是相同的,但更好记些。)。
6. 提交更新
$ git commit
这种方式会启动文本编辑器以便输入本次提交的说明。(默认会启用 shell 的环境变量 $EDITOR 所指定的软件,一般都是 vim 或 emacs。当然也可以使用 git config --global core.editor
命令设定你喜欢的编辑软件。)
另外也可以用 -m 参数后跟提交说明的方式,在一行命令中提交更新:
$ git commit -m “说明文字"
Git 提供了一个跳过使用暂存区域的方式,只要在提交的时候,给 git commit
加上-a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add
步骤:
$ git commit -a -m ‘文字说明'
7. 移除文件
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。可以用 git rm
命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了,如:
$ git rm 文件
如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f(译注:即 force 的首字母),以防误删除文件后丢失修改的内容。
另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。换句话说,仅是从跟踪清单中删除。比如一些大型日志文件或者一堆.a 编译文件,不小心纳入仓库后,要移除跟踪但不删除文件,以便稍后在 .gitignore 文件中补上,用 --cached 选项即可:
$ git rm --cached 文件
后面可以列出文件或者目录的名字,也可以使用 glob 模式。比方说:
$ git rm log/\*.log
注意到星号 * 之前的反斜杠 \,因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开(译注:实际上不加反斜杠也可以运行,只不过按照 shell 扩展的话,仅仅删除指定目录下的文件而不会递归匹配。上面的例子本来就指定了目录,所以效果等同,但下面的例子就会用递归方式匹配,所以必须加反斜杠。)。此命令删除所有log/ 目录下扩展名为 .log 的文件。类似的比如:
$ git rm \*~
会递归删除当前目录及其子目录中所有 ~ 结尾的文件。
8. 移动文件
$ git mv 文件_from 文件_to
其实,运行 git mv 就相当于运行了下面三条命令:
$ mv 文件_from 文件_to
$ git rm 文件_from
$ git add 文件_to
9. 查看提交历史
$ git log
选项说明:
-p 按补丁格式显示每个更新之间的差异。
--stat 显示每次更新的文件修改统计信息。
--shortstat 只显示 --stat 中最后的行数修改添加移除统计。
--name-only 仅在提交信息后显示已修改的文件清单。
--name-status 显示新增、修改、删除的文件清单。
--abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。
--relative-date 使用较短的相对时间显示(比如,“2 weeks ago”)。
--graph 显示 ASCII 图形表示的分支合并历史。
--pretty 使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。
-(n) 仅显示最近的 n 条提交
--since, --after 仅显示指定时间之后的提交。
--until, --before 仅显示指定时间之前的提交。
--author 仅显示指定作者相关的提交。
--committer 仅显示指定提交者相关的提交。
10. 撤消操作
10.1 修改最后一次提交
$ git commit --amend
此命令将使用当前的暂存区域快照提交。如果刚才提交完没有作任何改动,直接运行此命令的话,相当于有机会重新编辑提交说明,但将要提交的文件快照和之前的一样。
如果刚才提交时忘了暂存某些修改,可以先补上暂存操作,然后再运行 --amend
提交:
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
上面的三条命令最终只是产生一个提交,第二个提交命令修正了第一个的提交内容。
10.2 取消已经暂存的文件
$ git reset HEAD …
10.3 取消对文件的修改
$ git checkout -- …
11. 远程仓库
11.1 查看当前的远程库
git remote
查看当前配置的远程仓库。它会列出每个远程库的简短名字。在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使用这个名字来标识你所克隆的原始仓库;
-v :(译注:此为 --verbose 的简写,取首字母),显示对应的克隆地址;
11.2 添加远程仓库
git remote add [仓库名] [url]
添加一个新的远程仓库,指定名字为 仓库名
,以便将来引用;
11.3 从远程仓库抓取数据
$ git fetch [远程仓库名]
此命令会到名为 远程仓库名
的远程仓库中拉取所有你本地仓库中还没有的数据。运行完成后,你就可以在本地访问该远程仓库中的所有分支,将其中某个分支合并到本地,或者只是取出某个分支,一探究竟。
如果是克隆了一个仓库,此命令会自动将远程仓库归于 origin 名下。所以,git fetch origin
会抓取从你上次克隆以来别人上传到此远程仓库中的所有更新(或是上次 fetch 以来别人提交的更新)。有一点很重要,需要记住,fetch 命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合并。
如果设置了某个分支用于跟踪某个远端仓库的分支,可以使用 git pull
命令自动抓取数据下来,然后将远端分支自动合并到本地仓库中当前分支。在日常工作中我们经常这么用,既快且好。实际上,默认情况下 git clone
命令本质上就是自动创建了本地的 master 分支用于跟踪远程仓库中的 master 分支(假设远程仓库确实有 master 分支)。所以一般我们运行 git pull
,目的都是要从原始克隆的远端仓库中抓取数据后,合并到工作目录中的当前分支。
11.4 推送数据到远程仓库
git push [远程仓库S] [本地分支L]:[远程分支R]
表示:把 本地分支L
推送到 远程仓库S
的 远程分支R
中,如果 远程仓库S
中不存在 远程分支R
,则会在 远程仓库S
中 创建 远程分支R
并把 本地分支L
推送到 远程分支R
中;如果本地分支L和远程分支R名字相同,则可以简写为:
git push [远程仓库S] [本地分支L]
只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务。如果在你推数据前,已经有其他人推送了若干更新,那 你的推送操作就会被驳回。你必须先把他们的更新抓取到本地,合并到自己的项目中,然后才可以再次推送。
11.5 删除远程分支
git push [远程仓库S] :[远程分支R]
这个命令的格式意义比较无理头,为了方便记忆,可以这样理解:它是省略了本地分支名的推送命令 git push [远程仓库S] [本地分支L]:[远程分支R]
,省略 本地分支L
表示:在这里提取空白然后把它变成 远程分支R
。
11.6 查看远程仓库信息
git remote show [远程仓库名]
查看名为 远程仓库名
的远程仓库的详细信息
11.7 远程仓库的重命名
git remote rename [远程仓库旧名] [远程仓库新名]
修改某个远程仓库在本地的名称(新版 Git 中支持);
注意,对远程仓库的重命名,也会使对应的分支名称发生变化;
11.8 远程仓库的删除
git remote rm [远程仓库名]
12. 标签
12.1 列出已有的标签
git tag
12.2 新建标签
Git 使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated)。轻量级标签就像是个不会变化的分支,实际上它就是个指向特 定提交对象的引用。而含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标 签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。一般我们都建议使用含附注型的标签,以便保留相关信息;当然,如果只是临时性加注标签,或者不需要旁注额外信息,用轻量级标签也没问题。
含附注的标签:
创建一个含附注类型的标签非常简单,用 -a (译注:取 annotated 的首字母)指定标签名字即可:
$ git tag -a v1.4 -m 'my version 1.4’
而 -m 选项则指定了对应的标签说明,Git 会将此说明一同保存在标签对象中。如果没有给出该选项,Git 会启动文本编辑软件供你输入标签说明。
可以使用 git show
命令查看相应标签的版本信息,并连同显示打标签时的提交对象。
$ git show v1.4
轻量级标签:
轻量级标签实际上就是一个保存着对应提交对象的校验和信息的文件。要创建这样的标签,一个 -a,-s 或 -m 选项都不用,直接给出标签名字即可:
$ git tag v1.4-lw
12.3 签署标签
如果你有自己的私钥,还可以用 GPG 来签署标签,只需要把之前的 -a 改为 -s (译注: 取 signed 的首字母)即可:
$ git tag -s v1.5 -m 'my signed 1.5 tag’
12.4 验证标签
可以使用 git tag -v [标签名]
(译注:取 verify 的首字母)的方式验证已经签署的标签。此命令会调用 GPG 来验证签名,所以你需要有签署者的公钥,存放在 keyring 中,才能验证:
12.5 后期加注标签
我们忘了在提交 “updated rakefile” 后为此项目打上版本号 v1.2,没关系,现在也能做。只要在打标签的时候跟上对应提交对象的校验和(或前几位字符)即可:
$ git tag -a v1.2 9fceb02
12.6 分享标签
默认情况下,git push
并不会把标签传送到远端服务器上,只有通过显式命令才能分享标签到远端仓库。其命令格式如同推送分支,运行 git push origin [tagname]
即可;
如果要一次推送所有本地新增的标签上去,可以使用 --tags
选项;
13. 新建分支
$ git branch [分支名]
注意:此命令仅仅是建立了一个新的分支,但不会自动切换到这个分支中去;
14. 切换分支
$ git checkout [分支名]
15. 新建并切换分支
$ git checkout -b [分支名]
相当于以下2条命令:
$ git branch [分支名]
$ git checkout [分支名]
16. 合并分支
设当前分支为A
git merge [分支B]
此命令表示,把分支B合并到分支A
17. 删除分支
$ git branch -d [分支名]
18. 强制删除分支
$ git branch -D [分支名]
19. 查看当前分支列表
$ git branch
返回结果如下:
iss53
* master
testing
带有 *
的分支表示是当前所在的分支;
20. 查看各个分支最后一次提交对象的信息
$ git branch -v
21. 查看已经合并到当前所在分支的分支
$ git branch --merged
22. 查看未合并到当前所在分支的分支
$ git branch --no-merged
23. 跟踪远程分支
git checkout -b [分支名] [远程仓库名]/[分支名]
在1.6.2 以上版本的 Git,可以用 --track
选项简化:
$ git checkout --track [远程仓库名]/[分支名]
24. 删除远程分支
git push [远程仓库S] :[远程分支R]
这个命令的格式意义比较无理头,为了方便记忆,可以这样理解:它是省略了本地分支名的推送命令 git push [远程仓库S] [本地分支L]:[远程分支R]
,省略 本地分支L
表示:在这里提取空白然后把它变成 远程分支R
。
25. 分支的衍合
$ git rebase [主分支]
表示:以[主分支]为基础,以当前所在分支为[特性分支]进行衍合;衍合过程发生在当前所在分支;
$ git rebase [主分支] [特性分支]
表示:取出 [特性分支] ,然后在[主分支] 上重演:
六. 分支、HEAD、ref的区别
- ref 就是引用、指针的意思;
- Git 中的分支,其实本质上仅仅是个指向 提交(commit) 对象的可变指针;创建分支的过程就是创建分支指针;
- HEAD 是一个总是指向当前本地分支指针的指针,它表示当前分支;
七. 远程分支、远程跟踪分支、跟踪分支的区别
- 远程分支:在远程仓库中的分支,就是像本地分支一样的普通分支,只不过是在远程仓库里;
- 远程跟踪分支:本地仓库中用来代表远程分支的本地分支,它是只读的,只是表示远程分支的状态,本地不可修改;
- 跟踪分支:已跟踪了远程跟踪分支的本地分支,可以通过pull和push命令快捷地获取合并数据和推送数据;
远程跟踪分支 是 跟踪分支 与 远程分支 之间的跟踪桥梁;
八. 命令详解
1. 克隆clone
语法:
git clone [-b <远程分支>] [--single-branch] <远程仓库> [本地目录]
说明:
从 远程仓库
克隆指定的 远程分支
到 本地目录
下;
如果 本地目录
不存在,则会创建相应的本地目录;
选项:
-b <远程分支>
:创建指定 远程分支
的跟踪分支;如果不指定该选项,则会自动创建 master
跟踪分支;
--single-branch : 仅获取指定的单个分支的数据,并且仅创建指定分支的远程跟踪分支和跟踪分支;如果不指定该选项,则会获取远程仓库的所有分支的数据,并为远程仓库中的所有分支创建相应的远程跟踪分支;
2. 远程remote
remote 命令用于设置被当前本地仓库跟踪的远程仓库;
2.1 显示远程仓库信息
语法:
git remote [-v | --verbose]
说明:
显示所有的远程仓库;
选项:
-v, --verbose
:提供更多的信息;
2.2 添加远程仓库
语法:
git remote add {-t <远程分支>]} <远程仓库名>
说明:
添加新的远程仓库并命名为 远程仓库名
,设置其仓库地址为
;
远程仓库被添加之后,就可以用命令 git fetch <远程仓库名>
更新 远程跟踪分支;
选项:
-t <远程分支>
:创建指定的 远程分支
的远程跟踪分支;可以指定多个 -t <远程分支>
创建多个远程跟踪分支;
2.3 设置远程跟踪分支
语法:
git remote set-branches [--add] <远程仓库> <远程分支>...
说明:
重新为 远程仓库
的远程分支
设置 远程跟踪分支;
选项:
--add
:为 远程仓库
的远程分支
添加 远程跟踪分支;
3. 获取fetch
语法:
git fetch [选项] [<远程仓库> [[远程分支][:<本地分支>]]
说明:
从 远程仓库
获取 指定的 远程分支
的更新到相应的远程跟踪分支,并把数据同步到 本地分支
;
如果 本地分支
不存在,则会创建该本地分支;
如果省略了 本地分支
(如下)则只是取回指定 远程仓库
的指定 远程分支
的更新到到相应的远程跟踪分支;
git fetch [选项] <远程仓库> [远程分支]
如果省略 远程分支
和 本地分支
(如下)则会取回指定 远程仓库
的已被跟踪的所有远程分支的更新到相应的远程跟踪分支;
git fetch [选项] <远程仓库>
如果仅省略 远程分支
(如下)则会取回指定 远程仓库
的远 master
远程分支的更新到到相应的远程跟踪分支,并把数据同步到指定的 本地分支
;
git fetch [选项] <远程仓库> :<本地分支>
相当于:
git fetch [选项] <远程仓库> master:<本地分支>
如果省略 远程仓库
、 远程分支
和 本地分支
(如下)则会取回跟踪的所有仓库的已被跟踪的所有分支的更新到相应的远程跟踪分支;
git fetch [选项]
4. 拉取pull
语法:
git pull [选项] [<远程仓库> [[远程分支][:<本地分支>]]
说明:
从 远程仓库
获取指定的 远程分支
的更新到相应的远程跟踪分支,并合并到 本地分支
;
如果 本地分支
不存在,则会创建该本地分支;
5. 分支branch
5.1 显示或删除分支
语法:
git branch [选项]
说明:
显示或者删除(如果指定了删除选项)当前仓库的相关分支;
选项:
-d, --delete
:删除指定的分支;
-D
:强制删除指定的分支;
-a, --all
:显示远程跟踪分支和本地分支;
-r, --remotes
:显示或者删除远程跟踪分支;
-r, --remotes
:显示或者删除远程跟踪分支;
-v, -vv, --verbose
:提供更多的信息;注意:-v
和 -vv
提供的信息不一样;
5.2 创建分支
语法:
git branch [--set-upstream | --track] <分支名> [<起始指针>]
说明:
创建新分支并设置其名这 分支名
,且设置该分支的起始指针为 起始指针
;
选项:
--set-upstream | --track
:跟踪 起始指针
所指向的分支;
5.3 为分支设置上游分支(远程跟踪分支)
语法:
git branch (--set-upstream-to=<上游分支> | -u <上游分支>) [<分支>]
说明:
为指定的 分支
设置 上游分支
(即远程跟踪分支); 如果没有指定 分支
则默认使用当前所在分支;
6. 提交commit
语法:
git commit [--amend] [-m <提交说明>]
说明:
提交暂存的更新;
选项:
-m <提交说明>
:指定提交说明;如果不指定该选项,则会启动文本编辑器以便输入本次提交的说明;
--amend
:修改最后一次的提交;即不会生成新的提交对象;
7. 推送push
语法:
git push [-u | --set-upstream] [--tags] [远程仓库S] [本地分支L][:<远程分支R>]
说明:
- 表示:把
本地分支L
推送到远程仓库S
的远程分支R
中,如果远程仓库S
中不存在远程分支R
,则会在远程仓库S
中 创建远程分支R
并把本地分支L
推送到远程分支R
中; - 如果省略了
远程分支R
,即:git push [远程仓库S] [本地分支L]
,则会把本地分支L
推送到远程仓库S
中与本地分支L
同名的远程分支中; - 如果省略了
本地分支L
,即:git push [远程仓库S] :[远程分支R]
,则会删除远程仓库S
中的远程分支R
;
注意:
只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务。如果在你推数据前,已经有其他人推送了若干更新,那 你的推送操作就会被驳回。你必须先把他们的更新抓取到本地,合并到自己的项目中,然后才可以再次推送。
选项:
-u | --set-upstream
: 为推送的每一个分支设置设置上游分支(远程跟踪分支);
--tags
: 推送所有本地新增的标签到远程仓库;默认情况下,push
并不会把标签推送到远程仓库中,只有通过显式命令才能推送标签到远程仓库;
九. Git问题解决方案
1. 不显示中文
使用 git status
查看文件的状态时,如果文件名是中文,会显示形如 "\345\270\270\347\224\250\346\212\200\345\267\247.pages" 的情况;
解决方案:
配置core.quotepath的值为假:
git config --global core.quotepath false
2. 添加远程跟踪分支
当使用命令 git clone -b <远程分支> --single-branch <远程仓库> [本地目录]
只克隆指定的远程分支时,在本地仓库只会有指定远程分支的远程跟踪分支,如果要追加该远程仓库的其它分支的远程跟踪分支,可以按照如下操作:
解决方案:
- 添加远程跟踪分支
git remote set-branches --add <远程仓库> <远程分支>...
- 取回相应的
远程分支
的更新到该远程跟踪分支;
如果省略了本地分支
(如下)则只是取回指定远程仓库
的指定远程分支
的更新到到相应的远程跟踪分支;git fetch <远程仓库> [远程分支]
- 创建跟踪分支
git branch --track <分支名> [<远程跟踪分支>]
3. 把本地项目推送到新的远程仓库
当你想把本地已存在的项目放到远程仓库时,我们通常会在远程git上创建一个全新的空仓库,然后就会遇到这个问题:如何把已存在的项目上传到远程仓库,并跟踪该远程仓库?
解决方案:
注意: 如果该项目中已经有本地仓库了(即已经进行本地的版本控制了),则需要跳过前3步,从第4步开始;
- 在项目根目录下创建(初始化)本地仓库;
git init
- 暂存所有文件;
git add *
- 提交一次更新;
git commit -m "第1次提交"
- 添加远程仓库;
备注:git remote add <远程仓库名> <远程仓库的URL>
远程仓库名
是自定义的,只是为了方便引用; - 推送本地分支到远程仓库,并跟踪远程分支;
git push -u <远程仓库名> <本地分支>
4. 彻底删除文件或目录
如果我们直接删除某个文件或者目录,然后提交,这并不会把该文件从仓库中真正的删除,这个文件仍然存在仓库中,并为之前的版本会包含它;若需要从仓库中彻底删除文件或者目录(就像这个文件从一开始就不存在一样),则需要用 git 的 filter-branch 命令,它是 git 用来过滤的命令,具体解决方案如下:
解决方案:
-
从仓库中彻底删除文件:
命令如下:git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch <被删除的文件路径名>' --prune-empty --tag-name-filter cat -- --all
其中,
被删除的文件路径名
就是你要删除的文件或目录 相对于 相对于git仓库根目录 的相对路径。
注意:- 路径名不能以
/
开头,否则路径名会被认为是从 git 的安装目录开始的; - 如果要删除的目标不是文件夹,则需要在
git rm --cached
命令后面添加-r
选项,表示递归处理,将指定目录下的所有文件与子目录一并删除掉;
- 路径名不能以
-
强制推送修改后的更新到远程仓库:
git push --force --all
--force
选项表示以强制的方式推送; -
清理和回收空间:
通过以上步骤就已经从仓库的所有版本中删除了相应的文件或目录,但是原来的提交对象将被存储在.git/refs/original中,所以,若想彻底删除他们,则可以使用如下命令:$ rm -rf .git/refs/original/ $ git reflog expire --expire=now --all $ git gc --prune=now $ git gc --aggressive --prune=now