前言
git是一种很流行且高效的 VCS(版本控制系统),很多公司,组织和个人所使用,它可以很方便的管理版本,现在几乎所有IDE都集成了git,平常已经很少要自己手动敲git代码了。但是遇到复杂又不得不去翻手册。所以这篇文章对git 官网文档做了简短的总结,以方便后面快速查阅。
官网:https://git-scm.com/book/zh/v2
常用命令
#初始化项目
git init
# 拉仓库
git clone [url] [newrepositoryname]
# 查看远程仓库
git remote -v
#查看所有分支
git branch -a
# 查看当前状态
git status -s
#添加要跟踪的文件
git add [file]|[dir]
#提交
git commit -m {“something that you want to write”}
#查看提交历史
git log --pretty=format:"%h %s" --graph
#推送
git push origin local_banch:remote_banch
忽略文件
让git忽略项目中的一些文件是非常必要的。不然之后你肯定会因为各种配置文件,日志文件冲突而头疼。一开始就设置好要忽略的文件真的不要太好。
创建一个.gitignore的文件,文件 .gitignore 的格式规范如下:
-
所有空行或者以 # 开头的行都会被 Git 忽略。
-
可以使用标准的 glob 模式匹配。
-
匹配模式可以以(/)开头防止递归。
-
匹配模式可以以(/)结尾指定目录。
-
要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号()匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 使用两个星号() 表示匹配任意中间目录,比如
a/**/z
可以匹配 a/z, a/b/z 或a/b/c/z
等。
# no .a files
*.a
# but do track lib.a, even though you're ignoring .a files above
# 即使忽略了.a 文件照样可以跟踪(track)
!lib.a
# only ignore the TODO file in the current directory, not subdir/TODO
# 忽略文件,不忽略/TODO
/TODO
# ignore all files in the build/ directory
# 忽略文件夹
build/
# ignore doc/notes.txt, but not doc/server/arch.txt
# 统配文件
doc/*.txt
# ignore all .pdf files in the doc/ directory
#忽略中间文件
doc/**/*.pdf
git基本概念
文件状态和工作区
git 控制的文件有已提交(committed)、已修改(modified)和已暂存(staged)三种状态。git每一次操作之后,相应的状态的文件就会流入下一级工作区域且文件状态也得到了更正。
如:modified状态的文件经过stage 操作之后 文件进入staging area ,文件状态变成staged。commit 操作之后stageing area 中的文件会流入repository,状态会变成committed。
分支基本概念
commit之后git会创建文件,而这个文件保存者变化信息。git的分支就像一个指针,指向每次commit之后创建的变化文件。
而HEAD 是一个特殊指针,它指向当前本地分支。每次我们commit之后,当前分支和HEAD指针会指向新的commit
这样分支的两个重要概念就讲完了?
获取git 命令的帮助
获取 config命令的的帮助
git help config
配置git,告诉别人我是谁
Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:
-
/etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果使用带有 --system 选项的 git config 时,它会从此文件读写配置变量。
-
~/.gitconfig 或 ~/.config/git/config 文件:只针对当前用户。 可以传递 --global 选项让 Git 读写此文件。
-
当前使用仓库的 Git 目录中的 config 文件(就是 .git/config):针对该仓库。
每一个级别覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。
在 Windows 系统中,Git 会查找 $HOME 目录下(一般情况下是 C:\Users$USER)的 .gitconfig 文件。 Git 同样也会寻找 /etc/gitconfig 文件,但只限于 MSys 的根目录下,即安装 Git 时所选的目标位置
设置commit操作时messge 的内容
$ git config --global user.name "wen"
$ git config --global user.email wen@example.com
$ git config --global core.editor vscode
查看单个或全部的设置
$ git config user.name
$ git config --list
创建本地仓库
你有两种方法创建仓库,初始化一个项目和克隆别人的
初始化创建
进入相应目录运行如下命令
git init
仓库被初始化 但是还没被跟踪(track),该命令会创建默认master的分支
这样你就可以在文件下看见一个叫做.git的文件夹了。有一个原则就是任何时候都不要手动修改这个文件夹,
克隆仓库
添加远程仓库
git remote add <shortname> <url>
之后就可以用自己定义的shortname 来代替url了
查看远程仓库
git remote
#你也可以指定选项 -v,会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL。
git remote -v
如果你已经克隆了自己的仓库,那么至少应该能看到 origin - 这是 Git 给你克隆的仓库服务器的默认名字:、
远程仓库的移除与重命名
如果想要重命名引用的名字可以运行 git remote rename 去修改一个远程仓库的简写名。 例如,想要将 pb 重命名为 paul,可以用 git remote rename 这样做:
$ git remote rename pb paul
$ git remote
origin
paul
值得注意的是这同样也会修改你的远程分支名字。 那些过去引用 pb/master 的现在会引用 paul/master
如果因为一些原因想要移除一个远程仓库 - 你已经从服务器上搬走了或不再想使用某一个特定的镜像了,又或者某一个贡献者不再贡献了 - 可以使用 git remote rm :
$ git remote rm paul
$ git remote
origin
开始克隆
git clone [url] [newrepositoryname]
初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件(tracked file),并处于未修改状态。
如果你使用 clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以 “origin” 为简写。
git branch -a #查看所有分支
修改默认远程仓库名
#修改默认远程仓库名
git clone -o booyah
工作区操作
产看文件状态
$ git status
On branch master
nothing to commit, working directory clean
上述表示没有任何提交,且没有未被跟踪文件(Untracked file)
还可以加一个-s参数来简洁显示状态
$ git status -s|[--short]
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt
新添加的未跟踪文件前面有 ?? 标记,新添加到暂存区中的文件前面有 A 标记,修改过的文件前面有 M 标记。 你可能注意到了 M 有两个可以出现的位置,出现在右边的 M 表示该文件被修改了但是还没放入暂存区,出现在靠左边的 M 表示该文件被修改了并放入了暂存区。 例如,上面的状态报告显示: README 文件在工作区被修改了但是还没有将修改后的文件放入暂存区,lib/simplegit.rb 文件被修改了并将修改后的文件放入了暂存区。 而 Rakefile 在工作区被修改并提交到暂存区后又在工作区中被修改了,所以在暂存区和工作区都有该文件被修改了的记录。
跟踪文件或目录
克隆的项目中的文件全部会自动被添加为跟踪文件,而我们自己创建的文件需要手动添加为跟踪文件。不然git是不会记录该文件的变化的。这样做有一个好处就是一些我们不想跟踪的文件(配置文件,日志文件,环境文件)就不会进入版本控制系统中。这样在git 提交时不会老是报 合并冲突了。
git add [file]|[dir]
add 是一个多功能的文件,可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区(staged ),还能用于合并时把有冲突的文件标记为已解决状态等。 将这个命令理解为“添加内容到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。
查看待提交,已暂存,未暂存状态文件之间的详细区别
已修改(modified)和已暂存(staged)同文件的查重
git diff
此命令比较的是工作目录中当前文件和暂存区域快照之间的差异, 也就是修改之后还没有暂存起来的变化内容
已暂存(staged)和已提交(committed)同文件的查重
git diff --cached| [--cached]
Git 1.6.1 及更高版本还允许使用 git diff --staged,效果是相同的,但更好记些。)
图形化输出查重结果
git difftool
#查看系统支持那些difftool*
git difftool --tool-help
提交更新
快速提交
把已暂存的文件变成提交状态
git commit -m {“something that you want to write”}
$ git commit -m "Story 182: Fix benchmarks for speed"
[master 463dc4f] Story 182: Fix benchmarks for speed
2 files changed, 2 insertions(+)
create mode 100644 README
注意最好每次准备提交前,先用 git status 看下,是不是都已暂存起来了
可以看到,提交后它会告诉你,当前是在哪个分支(master)提交的,本次提交的完整 SHA-1 校验和是什么(463dc4f),以及在本次提交中,有多少文件修订过,多少行添加和删改过。
跳过使用暂存区域提交
给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: CONTRIBUTING.md
no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m 'added new benchmarks'
[master 83e38c7] added new benchmarks
1 file changed, 5 insertions(+), 0 deletions(-)
详情提交
git commit
这种方式会启动一个文本编辑器,来发送commit时候需要附带的message(告诉别人或自己提交了什么)。默认会启用 shell 的环境变量 $EDITOR 所指定的软件,一般都是 vim 或 emacs。当然也使用 git config --global core.editor 命令设定你喜欢的编辑软件。)类似如下文本:
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# new file: README
# modified: CONTRIBUTING.md
#
~
~
~
".git/COMMIT_EDITMSG" 9L, 283C
默认的提交消息包含最后一次运行 git status 的输出,如果想要更详细的对修改了哪些内容的提示,可以用 -v 选项,这会将你所做的改变的 diff 输出放到编辑器中从而使你知道本次提交具体做了哪些修改。
git commit -v
移除跟踪清单或暂缓区的文件
从暂缓区删除,但是保留文件在磁盘
git rm --cached [fime| dir]
且支持glob 模式详情看上面的忽略文件,如下
$ git rm log/\*.log
$ git rm \*~
从跟踪清单中删除文件,且从磁盘中删除文件
如果手动删除,会提示更改not staged 。还学要commit 。git才会把产出动不到库中
$ rm PROJECTS.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: PROJECTS.md
no changes added to commit (use "git add" and/or "git commit -a")
git rm 删除文件,会提示已经commit
$ git rm PROJECTS.md
rm 'PROJECTS.md'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: PROJECTS.md
从暂缓区中删除文件,且从磁盘中删除文件
git rm -f
删除暂缓和跟踪清单中的文件都是不可逆的
移动或重命名文件
$ git mv file_from file_to
如下面实例所示:
$ git mv README.md README
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> README
不像其它的 VCS 系统,Git 并不显式跟踪文件移动操作 。不过 Git 非常聪明,它会推断出究竟发生了什么。git mv 是一个复合命令,实际是调用希迈纳三个命令
$ mv README.md README
$ git rm README.md
$ git add README
查看本地提交历史
#这个是我最常用的,其他的可以看官方链接
git log --pretty=format:"%h %s" --graph
撤销操作
重新提交(commit)
如果你commit之后发现遗漏了些文件,或者message写错了,你可以用git commit --amend在重新提交以下
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
最终你只会有一个提交 - 第二次提交将代替第一次提交的结果。
取消暂存的文件
to staged之后很后悔可以用下列命令,撤销操作
git reset HEAD <file>
HEAD 为上一次提交的快照,下一次提交的父结点
–hard 选项可以令 git reset 成为一个危险的命令(译注:可能导致工作目录中所有当前进度丢失!)
撤消对文件的修改
git 没有撤销not staged文件的功能,到那时可以用checkout 回退到之前提交的版本。完成对文件修改的撤销
git checkout -- [file]
你需要知道 git checkout – [file] 是一个危险的命令,这很重要。 你对那个文件做的任何修改都会消失 - 你只是拷贝了另一个文件来覆盖它。 除非你确实清楚不想要那个文件了,否则不要使用这个命令。
如果你仍然想保留对那个文件做出的修改,但是现在仍然需要撤消,你可兴建一个分支然后commit在切换回来撤销操作
记住,在 Git 中任何 已提交的 东西几乎总是可以恢复的。 甚至那些被删除的分支中的提交或使用 --amend 选项覆盖的提交也可以恢复(阅读 数据恢复 了解数据恢复)。 然而,任何你未提交的东西丢失后很可能再也找不到了。
分支操作
创建分支
git branch <branchname>
git 默认分支为master,在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。 它会在每次的提交操作中自动向前移动。
Git 的 “master” 分支并不是一个特殊分支。 它就跟其它分支完全没有区别。 之所以几乎每一个仓库都有 master 分支,是因为 git init 命令默认创建它,并且大多数人都懒得去改动它。
git branch 命令仅仅 创建 一个新分支,并不会自动切换到新分支中去。
分支切换
git checkout master
这条命令做了两件事。一是使 HEAD 指回 master 分支,二是将工作目录恢复成 master 分支所指向的快照内容。 也就是说,你现在做修改的话,项目将始于一个较旧的版本。 本质上来讲,这就是忽略之前分支所做的修改,以便于向另一个方向进行开发。
checkout 操作之前你要留意你的工作目录和暂存区里那些还没有被提交的修改,它可能会和你即将检出的分支产生冲突从而阻止 Git 切换到该分支。 最好的方法是,在你切换分支之前,保持好一个干净的状态。 有一些方法可以绕过这个问题即,保存进度(stashing) 和 修补提交(commit amending),我们会在 储藏与清理 中看到关于这两个命令的介绍。
新建并创建切换分支
# -b参数可以新建且切换分支
git checkout -b iss53
fast-forward分支合并
$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
在合并的时候,你应该注意到了"快进(fast-forward)"这个词。 由于当前 master 分支所指向的提交是你当前提交(有关 hotfix 的提交)的直接上游,所以 Git 只是简单的将指针向前移动。 换句话说,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。
diverged分支合并
$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件:
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")
任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。 出现冲突的文件会包含一些特殊区段,看起来像下面这个样子:
<<<<<<< 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 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。 为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。 例如,你可以通过把这段内容换成下面的样子来解决冲突:
<div id="footer">
please contact us at email.support@github.com
</div>
上述的冲突解决方案仅保留了其中一个分支的修改,并且 <<<<<<< , ======= , 和 >>>>>>> 这些行被完全删除了。 在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。
也可以运行 git reset --hard HEAD 回到之前的状态或其他你想要恢复的状态。 请牢记这会将清除工作目录中的所有内容,所以确保你不需要保存这里的任意改动。
图形化修改
git mergetool
查看分支
通过git log 查看分支
你可以简单地使用 git log --decorate命令查看各个分支当前所指的对象。
$ git log --oneline --decorate
f30ab (HEAD, master, testing) add feature #32 - ability to add new
34ac2 fixed bug #1328 - stack overflow under certain conditions
98ca9 initial commit of my project
正如你所见,当前 “master” 和 “testing” 分支均指向校验和以 f30ab 开头的commit对象。
运行 git log --oneline --decorate --graph --all ,它会输出你的提交历史、各个分支的指向以及项目的分支分叉情况。
$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) made other changes
| * 87ab2 (testing) made a change
|/
* f30ab add feature #32 - ability to add new formats to the
* 34ac2 fixed bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project
通过branch 查看分支
不加参数的 branch命令会显示当前分支状况
$ git branch
iss53
* master
testing
星号表示HEAD指向的分支
-v参数查看分支最后一次提交
$ git branch -vv
iss53 93b412c fix javascript issue
* master 7a98805 Merge branch 'iss53'
testing 782fd34 add scott to the author list in the readmes
如果要查看哪些分支已经合并到当前分支,可以运行 git branch --merged:
$ git branch --merged
iss53
* master
因为之前已经合并了 iss53 分支,所以现在看到它在列表中。 在这个列表中分支名字前没有 * 号的分支通常可以使用 git branch -d 删除掉;因为你已经将它们的工作整合到了另一个分支,所以并不会失去任何东西。
查看所有包含未合并工作的分支,可以运行 git branch --no-merged:
git branch --no-merged
testing
testing 没有合并master 分支。
删除分支
# -d删除分支
git branch -d hotfix
强制删除未合并的分支
这里显示了其他分支。 因为它包含了还未合并的工作,尝试使用 git branch -d 命令删除它时会失败
$ git branch -d testing
error: The branch 'testing' is not fully merged.
If you are sure you want to delete it, run 'git branch -D testing'.
如果真的想要删除分支并丢掉那些工作,如同帮助信息里所指出的,可以使用 -D 选项强制删除它。
远程分支
基本概念
当我们从远程仓库中clone 一个项目之后,git会创建一个远程分支和一个maste分支,远程分支默认情况下 . 它们是你不能移动,当你做任何网络通信操作时(抓取或者推送时),它们会自动移动。 远程分支像是你上次连接到远程仓库时的书签,保持着服务器端的引用状态。它们以 (remote)/(branch) 形式命名
修改默认远程分支名称
默认的远程分支为origin/master 你可以通过下列语句来修改默认的名称
git clone -o booyah
查看远程分支状态
当线上有人更新了分支而你在本地也更新了你自己的分支。且你没有做链接操作。这时结构如下
本地的远程分支没有前进。你可以用下列命令去看远程服务器的分支状态
git ls-remote (remote)#远程分支列表
git remote show (remote)#详细信息
查看远程仓库分支
如果想要查看某一个远程仓库的更多信息,可以使用 如下命令
git remote show [remote-name]
像下面这样
$ git remote show origin
* remote origin
Fetch URL: https://github.com/schacon/ticgit
Push URL: https://github.com/schacon/ticgit
HEAD branch: master
Remote branches:
master tracked
dev-branch tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)
它同样会列出远程仓库的 URL 与跟踪分支的信息。 这些信息非常有用,它告诉你正处于 master 分支,并且如果运行 git pull,就会抓取所有的远程引用,然后将远程 master 分支合并到本地 master 分支。 它也会列出拉取到的所有远程引用。
这是一个经常遇到的简单例子。 如果你是 Git 的重度使用者,那么还可以通过 git remote show 看到更多的信息。
$ git remote show origin
* remote origin
URL: https://github.com/my-org/complex-project
Fetch URL: https://github.com/my-org/complex-project
Push URL: https://github.com/my-org/complex-project
HEAD branch: master
Remote branches:
master tracked
dev-branch tracked
markdown-strip tracked
issue-43 new (next fetch will store in remotes/origin)
issue-45 new (next fetch will store in remotes/origin)
refs/remotes/origin/issue-11 stale (use 'git remote prune' to remove)
Local branches configured for 'git pull':
dev-branch merges with remote dev-branch
master merges with remote master
Local refs configured for 'git push':
dev-branch pushes to dev-branch (up to date)
markdown-strip pushes to markdown-strip (up to date)
master pushes to master (up to date)
这个命令列出了当你在特定的分支上执行 git push 会自动地推送到哪一个远程分支。 它也同样地列出了哪些远程分支不在你的本地,哪些远程分支已经从服务器上移除了,还有当你执行 git pull 时哪些分支会自动合并。
更新(抓取)远程分支
git fetch origin
这个命令会查找 “origin” 是哪一个服务器(在本例中,它是 git.ourcompany.com),从中抓取本地没有的数据,并且更新本地数据库,移动 origin/master 指针指向新的、更新后的位置。注意fetch不会创建跟踪分支(后面讲什么是跟踪分支)
最后对于多个远程仓库的合并如下托所示
移动之后的样子
删除远程分支
假设你已经通过远程分支做完所有的工作了 - 也就是说你和你的协作者已经完成了一个特性并且将其合并到了远程仓库的 master 分支(或任何其他稳定代码分支)。 可以运行带有 --delete 选项的 git push 命令来删除一个远程分支。 如果想要从服务器上删除 serverfix 分支,运行下面的命令:
$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
- [deleted] serverfix
基本上这个命令做的只是从服务器上移除这个指针。 Git 服务器通常会保留数据一段时间直到垃圾回收运行,所以如果不小心删除掉了,通常是很容易恢复的。
跟踪分支
如果想要在远程分支上创建一个新的分支,并·切换上去,可以使用下列命令
git checkout -b local_banch origin/remote_banch
这个新的local_banch 就是就叫跟踪分支,它有别于普通的分支,他保持了远程分支的状态。此时我麦可以称remote_banch为上游分支
之后使用下列命令会自动去上游分支服务器上抓取代码,并合并local_banch和remote_banch
git pull local_banch
当克隆一个仓库时,它通常会自动地创建一个跟踪 origin/master 的 master 分支。 然而,如果你愿意的话可以设置其他的跟踪分支 。如果名字本地分支和远程分支名字相同你可以使用下列简写
git checkout --track [remotename]/[branch]
修改跟踪分支
设置已有的本地分支跟踪一个刚刚拉取下来的远程分支,或者想要修改正在跟踪的上游分支,你可以在任意时间使用 -u 或 --set-upstream-to 选项运行 git branch 来显式地设置。
$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
上游快捷方式
当设置好跟踪分支后,可以通过 @{upstream} 或 @{u} 快捷方式来引用它。 所以在 master 分支时并且它正在跟踪 origin/master 时,如果愿意的话可以使用 git merge @{u} 来取代 git merge origin/master。
查看跟踪分支
如果想要查看设置的所有跟踪分支,可以使用 git branch 的 -v 选项。 这会将所有的本地分支列出来并且包含更多的信息,如每一个分支正在跟踪哪个远程分支与本地分支是否是领先、落后或是都有。
git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets
master 1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
testing 5ea463a trying something new
这里可以看到 iss53 分支正在跟踪 origin/iss53 并且 “ahead” 是 2,意味着本地有两个提交还没有推送到服务器上。 也能看到 master 分支正在跟踪 origin/master 分支并且是最新的。 接下来可以看到 serverfix 分支正在跟踪 teamone 服务器上的 server-fix-good 分支并且领先 3 落后 1,意味着服务器上有一次提交还没有合并入同时本地有三次提交还没有推送。 最后看到 testing 分支并没有跟踪任何远程分支。
需要重点注意的一点是这些数字的值来自于你从每个服务器上最后一次抓取的数据。 这个命令并没有连接服务器,它只会告诉你关于本地缓存的服务器数据。 如果想要统计最新的领先与落后数字,需要在运行此命令前抓取所有的远程仓库。 可以像这样做:git fetch --all; git branch -vv
pull与fetch 区别
$ git fetch <remote-name>[remote_branch_name]
-
这个命令会访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。
-
如果你使用 clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以 “origin” 为简写。 所以,git fetch origin 会抓取克隆(或上一次抓取)后新推送的所有工作。
-
必须注意 git fetch 命令会将数据拉取到你的本地仓库 - 它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。
$ git pull remote_branch_name
-
这条命令只用于远程仓库
-
git clone 命令会自动设置本地 master 分支跟踪克隆的远程仓库的 master 分支(或不管是什么名字的默认分支)。 运行 git pull 通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支。
-
当 git fetch 命令从服务器上抓取本地没有的数据时,它并不会修改工作目录中的内容。 它只会获取数据然后让你自己合并。 然而,有一个命令叫作 git pull 在大多数情况下它的含义是一个 git fetch 紧接着一个 git merge 命令。 如果有一个像之前章节中演示的设置好的跟踪分支,不管它是显式地设置还是通过 clone 或 checkout 命令为你创建的,git pull 都会查找当前分支所跟踪的服务器与分支,从服务器上抓取数据然后尝试合并入那个远程分支。
-
由于 git pull 的魔法经常令人困惑所以通常单独显式地使用 fetch 与 merge 命令会更好一些。
推送跟踪分支
当我想把代码推上远程分支时可以使用下列命令
git push origin local_banch:remote_banch
#同名的话可以省略
git push origin local_banch
之后别人就可以通过fetch来获得新的远程分支了。他们就可以像使用本地分支一样使用远程分支比如合并
git merge origin/remote_banch
推送分支到远程仓库
当你想分享你的项目时,必须将其推送到上游。 这个命令很简单:git push [remote-name] [branch-name]。 当你想要将 master 分支推送到 origin 服务器时(再次说明,克隆时通常会自动帮你设置好那两个名字),那么运行这个命令就可以将你所做的备份到服务器:
git push origin master
只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先将他们的工作拉取下来并将其合并进你的工作后才能推送
格式如下:
git push (remote) (branch):
再例如:
$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
* [new branch] serverfix -> serverfix
这里有些工作被简化了。 Git 自动将 serverfix 分支名字展开为 refs/heads/serverfix:refs/heads/serverfix,那意味着,“推送本地的 serverfix 分支来更新远程仓库上的 serverfix 分支。” 我们将会详细学习 Git 内部原理 的 refs/heads/ 部分,但是现在可以先把它放在儿。 你也可以运行 git push origin serverfix:serverfix,它会做同样的事 - 相当于它说,“推送本地的 serverfix 分支,将其作为远程仓库的 serverfix 分支” 可以通过这种格式来推送本地分支到一个命名不相同的远程分支。 如果并不想让远程仓库上的分支叫做 serverfix,可以运行 git push origin serverfix:awesomebranch 来将本地的 serverfix 分支推送到远程仓库上的 awesomebranch 分支。
只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先将他们的工作拉取下来并将其合并进你的工作后才能推送。 阅读 Git 分支 了解如何推送到远程仓库服务器的详细信息。
这样本地链条和远程链条不同的部分就重新在远程仓库上分叉,末梢就是我们定义的名字。上例中awesomebranch
变基
基本概念
使用merge 根据C2 把C3和C4合并成C5,其实为了合并C3和C4还有一种方法叫做变基。你可以使用 rebase 命令将提交到某一分支上的所有修改都移至另一分支上。如果使用merge的话,它首先找到这两个分支(即当前分支 experiment、变基操作的目标基底分支 master)的最近共同祖先 C2,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件,然后将当前分支指向目标基底 C3, 最后以此将之前另存为临时文件的修改依序应用。
此时,C4’ 指向的快照就和上面使用 merge 命令的例子中 C5 指向的快照一模一样了。 这两种整合方法的最终结果没有任何区别,但是变基使得提交历史更加整洁。 你在查看一个经过变基的分支的历史记录时会发现,尽管实际的开发工作是并行的,但它们看上去就像是串行的一样,提交历史是一条直线没有分叉。
一般我们这样做的目的是为了确保在向远程分支推送时能保持提交历史的整洁——例如向某个其他人维护的项目贡献代码时。 在这种情况下,你首先在自己的分支里进行开发,当开发完成时你需要先将你的代码变基到 origin/master 上,然后再向主项目提交修改。 这样的话,该项目的维护者就不再需要进行整合工作,只需要快进合并便可。
请注意,无论是通过变基,还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。 变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。
git 凭证免密登陆
git 有两种免密登陆的方式
- 一SSH 链接的 证书免密码登陆
- HTTPS凭证 免密码登陆
现在我们谈凭证免密码登陆。git 有一整套凭证系统来完成免密登陆。下面是凭证登陆的一些模式(配置参数)
-
默认所有都不缓存。 每一次连接都会询问你的用户名和密码。
-
“cache” 模式会将凭证存放在内存中一段时间。 密码永远不会被存储在磁盘中,并且在15分钟后从内存中清除。
-
“store” 模式会将凭证用明文的形式存放在磁盘中,并且永不过期。 这意味着除非你修改了你在 Git 服务器上的密码,否则你永远不需要再次输入你的凭证信息。 这种方式的缺点是你的密码是用明文的方式存放在你的 home 目录下。
-
如果你使用的是 Mac,Git 还有一种 “osxkeychain” 模式,它会将凭证缓存到你系统用户的钥匙串中。 这种方式将凭证存放在磁盘中,并且永不过期,但是是被加密的,这种加密方式与存放 HTTPS 凭证以及 Safari 的自动填写是相同的。
-
如果你使用的是 Windows,你可以安装一个叫做 “winstore” 的辅助工具。 这和上面说的 “osxkeychain” 十分类似,但是是使用 Windows Credential Store 来控制敏感信息。 可以在 https://gitcredentialstore.codeplex.com 下载。
git config --global credential.helper cache
部分模式都一些候选项:
“store” 模式可以接受一个 --file
参数,可以自定义存放密码的文件路径(默认是 ~/.git-credentials
)。 “cache” 模式有 --timeout 参数,可以设置后台进程的存活时间(默认是 “900”,也就是 15 分钟)。 下面是一个配置 “store” 模式自定义路径的例子:
$ git config --global credential.helper store --file ~/.my-credentials
Git 甚至允许你配置多个辅助工具。 当查找特定服务器的凭证时,Git 会按顺序查询,并且在找到第一个回答时停止查询。 当保存凭证时,Git 会将用户名和密码发送给 所有 配置列表中的辅助工具,它们会按自己的方式处理用户名和密码。 如果你在闪存上有一个凭证文件,但又希望在该闪存被拔出的情况下使用内存缓存来保存用户名密码,.gitconfig 配置文件如下
[credential]
helper = store --file /mnt/thumbdrive/.git-credentials
helper = cache --timeout 30000
查看模式:
git config --global credential.helper
更多内容请看
留个坑
如何合理管理使用分支
详情请看:https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94%AF%E5%BC%80%E5%8F%91%E5%B7%A5%E4%BD%9C%E6%B5%81
https://git-scm.com/book/zh/v2/Git-%E5%88%86%E6%94%AF-%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF
打标签
留个坑
https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-%E6%89%93%E6%A0%87%E7%AD%BE
别名
https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-Git-%E5%88%AB%E5%90%8D