Git近年来受到欢迎。版本代码控制系统被Linux等巨大的开源项目所使用,成千上万的贡献者,各类规模的团队,独立开发者,甚至是学生。node
初学者经常被git所要求的全部神秘的命令和参数所吓倒。面试常常也会问到git 命令。你能够开始掌握一些最经常使用的,而后从在慢慢进一步学习。linux
Git是一个命令行实用程序的集合,它会跟踪和记录文件中的更改(一般是源代码,可是能够跟踪任何你想要的文件)。 有了它,你能够恢复项目的旧版本,比较,分析,合并更改等操做。 这个过程被称为版本控制。 有许多版本控制系统能够完成这项工做。 你可能据说过其中的一些--SVN,Mercurial,Perforce,CVS,Bitkeeper等等。 Git是分散的,这意味着它不依赖于中央服务器来保留文件的旧版本。 相反,它彻底在本地运行,将这些数据做为一个文件夹存储在硬盘上,咱们称之为储存仓库。 可是,你也能够在线存储您的仓库的副本,这使得多我的能够轻松协做并使用相同的代码。这就是像GitHub和BitBucket这样的网站所使用的同样。git
在你的设备上安装Git很简单: Linux - 只需打开一个新的终端,并经过发行版的软件包管理器安装git。 对于Ubuntu的命令是: sudo apt-get install git Windows - 咱们推荐 git for windows, 由于它提供了一个GUI可视化客户端和一个BASH命令行模拟器。 OS X - 最简单的方法是安装 自助软件,而后brew install git从终端 运行。 若是你是一个绝对的初学者,那么一个图形化的git客户端是必须的。 我强烈推荐使用GitHub Desktop和Sourcetree,可是还有许多其余好的和免费的在线。 即便使用GUI应用程序,了解基本的git命令仍然很重要,所以在本文剩下的部分中,这将是咱们惟一说的重点。github
如今咱们已经在咱们的计算机上安装了git,咱们将须要添加一些快速配置。 有不少能够摆弄的选项,可是咱们要设置最重要的选项:咱们的用户名和电子邮件。 打开一个终端并运行这些命令:面试
$ git config --global user.name "My Name"
$ git config --global user.email myEmail@example.com
复制代码
咱们在Git中所作的每个动做如今都会贴上咱们的名字和地址。 这样用户老是知道谁作了什么,一切都更有条理。windows
正如咱们前面提到的,git将它的文件和历史记录直接存储在项目文件夹中。要创建一个新的存储库,咱们须要打开一个终端,导航到咱们的项目目录并运行git init。这将打开Git这个特定的文件夹,并建立一个隐藏的.git目录,其中存储库的历史和配置。数组
在桌面上建立一个名为git_exercise的文件夹,打开一个新的终端并输入如下内容:浏览器
$ cd Desktop/git_exercise/
$ git init
命令行应该按照如下方式输出:
Initialized empty Git repository in /home/user/Desktop/git_exercise/.git/
复制代码
这意味着咱们的已经成功建立,但内容仍然是空的。如今建立一个名为hello.txt的简单文本文件,并将其保存在git_exercise文件夹中。安全
4.检查状态 - git statusbash
Git status 是另外一个必须知道的命令,它返回关于仓库当前状态的信息:一切是最新的信心,那些是最新的,哪些是改变的,等等。 运行git status 在咱们新建立的Log应该返回如下内容:
$ git status
On branch master
Initial commit
Untracked files: (use "git add ..." to include in what will be committed)
hello.tx
复制代码
返回的消息指出hello.txt未被跟踪。这意味着文件是新的,Git不知道它是否应该跟踪发生在这个文件上的变化,或者忽略它。为了确认新文件,咱们须要对其进行分类。
5.添加 - git add Git有一个“暂存区”的概念。你能够把它想象成一个空白的画布,它保存着你想要提交的变化。它开始是空的,但你能够用命令添加文件(甚至是单行和部分文件)git add,最后提交全部的文件(建立一个快照)git commit。 文件:
$ git add hello
.
txt
复制代码
若是咱们想在目录中添加全部内容,咱们可使用:
$ git add
-
A
复制代码
再次检查状态 输入 git status应该返回之前的不一样输出。
$ git status
On branch master
Initial commit Changes to be committed:
(use "git rm --cached ..."to unstage)
new file: hello.txt
复制代码
咱们的文件已准备好提交。 状态消息还提示咱们暂存区中的文件有什么变化 - 在这种状况下是 新文件,可是能够修改或删除它,这取决于自上次文件发生了什么git add。
6.提交 - git commit
一个提交表示在给定的时间点咱们的仓库的状态。这就像一个日志记录,咱们能够回顾一下,看看咱们拿什么。
要建立一个新的提交,咱们须要至少有一个更改添加到暂存区域(咱们这样作 git add),而后运行如下命令:
$ git commit
-
m
"Initial commit."
复制代码
这将建立一个新的提交,其中包含来自暂存区域的全部更改(添加hello.txt)。 该-m "Initial commmit"部分是用户自定义的描述,总结了在该提交中所作的更改。 常常提交并老是编写有意义的提交消息,被认为一个开发者的好习惯。
远程仓库
如今咱们的提交是本地的 - 它只存在于.git文件夹中。虽然本地存储库自己是有用的,但在大多数状况下,咱们都但愿共享咱们的工做并将其部署到服务器或存储库托管服务。
为了上传东西到一个远程的响应,咱们首先必须创建一个链接。 为了配合本文,咱们的存储库的地址将是https://github.com/Tamic/novate。 咱们建议放在在GitHub,BitBucket或任何其余服务中建立本身的空存储库。 注册和设置可能须要等待一段时间,但全部服务都提供了很好的分步指南文档来帮助你。
要将咱们的本地存储库与GitHub上的存储库链接起来,咱们在终端中执行如下行: 文件:
# 链接到远程服务器
$ git remote add origin https
:
//github.com/Tamic/novate.git
复制代码
项目可能同时拥有多个远程仓库。为了可以区分他们,咱们给他们不一样的名字。 传统上git中的主远程仓库被称为origin。
如今是时候把咱们的本地提交转移到服务器上了。 这个过程被称为推送(push),而且每当咱们想要更新远程仓库就完成了。 Git命令是这样作的,git push而且须要两个参数 - 远程回购(咱们称之为咱们的 产地)的名称和推到的分支(master是每一个反馈的默认分支)。
$ git push origin master
Counting
objects
:
3
,
done
.
Writing
objects
:
100
%
(
3
/
3
),
212
bytes
|
0
bytes
/
s
,
done
.
Total
3
(
delta
0
),
reused
0
(
delta
0
)
To https://github.com/Tamic/novate.git *
[new branch ] | master -> master
复制代码
根据你使用的远程服务,你将须要验证本身的密码和帐号。 若是一切正常完成,当你在你的网络浏览器中进入前面建立的远程仓库时, hello.txt 应该在那里,而且能够打开阅读。
此时,你们能够在Github上查看和浏览远程仓库库。他们能够在本地下载,并使用如下git clone命令得到项目的完整工做副本:
$ git push origin master
$ git clone https
:
//github.com/Tamic/novate.git
复制代码
自动建立一个新的本地仓库,并将github版本配置为远程。
若是你的代码仓库进行了更新,则可使用下面单个命令下载更改 - git pull:
$ git pull origin master
From
https
:
//github.com/Tamic/novate.git
*
branch master
->
FETCH_HEAD
Already
up
-
to
-
date
.
复制代码
因为咱们克隆的没有 没有其余人提交新的文件或者修改,下载时候提示没有任何变化。
在开发一个新功能时,考虑一个原始项目的副本,称为分支,也被认为开发者的一个好习惯 。分支有他们本身的历史记录,并将他们之间的变化隔离开来,直到你决定把它们合并在一块儿。 这是因为如下几个缘由:
一个已经工做,稳定的代码版本不会被破坏。 许多功能能够由不一样的人本身立马并能安全稳定的开发。 开发人员能够在本身的分支上工做,而不会由于别人的工做而改变代码库的风险。 当不肯定什么是最好的时候,能够在不一样的分支上开发相同特征的多个版本,而后进行比较。
每一个存储库的默认分支称为 主(Master)分支。 要建立更多分支,请使用如下git branch 命令:
$ git branch amazing_new_feature
复制代码
这只是建立了新的分支,在这一点上是彻底同样的,咱们的主干。
2.切换分支 - git checkout
如今,当咱们运行时git branch,咱们会看到有两个选项可用:
$ git branch
amazing_new_feature
*
master
复制代码
Master是当前分支,并标有星号。可是,咱们想要使用咱们的新功能,因此咱们须要切换到另外一个分支。这是用git checkout命令完成的,须要一个参数 - 要切换到的分支名称。
$ git checkout amazing_new_feature
复制代码
git的“惊人的新功能”将成为另外一个名为feature.txt的文本文件。 咱们将建立它,add它,并commit。
$ git add feature.txt
$ git commit -m “新功能完成”。
复制代码
新功能完成后,咱们能够切回到主分支。
$ git checkout master
复制代码
如今,若是咱们在文件浏览器中打开咱们的项目,咱们会注意到feature.txt 已经消失了。那是由于咱们回到了master分支,而这里feature.txt 历来没有被建立过。为了实现这个目标,咱们须要将这git merge两个分支结合在一块儿,将在 amazing_new_feature中完成的更改应用于项目的主版本。
git合并amazing_new_feature
复制代码
主分支如今是最新的。awesome_new_feature分支再也不须要,能够删除。
git branch -d amazing_new_feature
复制代码
在本文的最后一节中,我将介绍一些更高级的技术,这些技术极可能在你工做中派上用场。 1.检查提交之间的差别 每一个提交都以数字和符号的字符串形式存在惟一的ID。 要查看全部提交及其ID的列表,咱们可使用git log:
$ git log
commit ba25c0ff30e1b2f0259157b42b9f8f5d174d80d7
Author
:
Tutorialzine
Date
:
Mon
May
30
17
:
15
:
28
2016
+
0300
New
feature complete
commit b10cc1238e355c02a044ef9f9860811ff605c9b4
Author
:
Tutorialzine
Date
:
Mon
May
30
16
:
30
:
04
2016
+
0300
Added
content to hello
.
txt
commit
09bd8cc171d7084e78e4d118a2346b7487dca059
Author
:
Tutorialzine
Date
:
Sat
May
28
17
:
52
:
14
2016
+
0300
Initial
commit
复制代码
正如你所看到的,ID是很长的,可是和它们一块儿工做时,没有必要复制整个东西 - 前几个符号一般就足够了。
要查看提交中的新增内容,咱们能够运行git show [commit]:
$ git show b10cc123
commit b10cc1238e355c02a044ef9f9860811ff605c9b4
Author
:
Tutorialzine
Date
:
Mon
May
30
16
:
30
:
04
2016
+
0300
Added
content to hello
.
txt
diff
--
git a
/
hello
.
txt b
/
hello
.
txt
index e69de29
..
b546a21
100644
---
a
/
hello
.
txt
+++
b
/
hello
.
txt
@@
-
0
,
0
+
1
@@
+
Nice
weather today
,
isn
't it? 复制代码
要查看任何两个提交之间的区别,咱们可使用 git diff[commit-from] .. [commit-to]语法:
$ git diff
09bd8cc
..
ba25c0ff
diff
--
git a
/
feature
.
txt b
/
feature
.
txt
new
file mode
100644
index
0000000.
.
e69de29
diff
--
git a
/
hello
.
txt b
/
hello
.
txt
index e69de29
..
b546a21
100644
---
a
/
hello
.
txt
+++
b
/
hello
.
txt
@@
-
0
,
0
+
1
@@
+
Nice
weather today
,
isn
't it? 复制代码
咱们已经比较了第一次提交和最后一次提交,因此咱们看到了全部的改变。 一般使用这个git difftool命令能够更容易地完成这个任务,这个命令可让一个图形化的客户端显示全部的差别。
Git容许咱们将任何选定的文件返回到某个提交中的方式。这是经过git checkout 咱们之前用来切换分支的熟悉的命令完成的,可是也能够用来在提交之间切换(在Git中一个命令用于多个看起来不相关的任务是很常见的)。 在下面的例子中,咱们将采用hello.txt,并将自从初始提交以来所作的一切都撤销。 要作到这一点,咱们必须提供咱们想要返回的提交的id,以及咱们文件的完整路径。
$ git checkout 09bd8cc1 hello.txt
复制代码
若是你注意到你在提交信息中输入了一个错字,或者你忘记了添加一个文件,而且在提交以后你看到了,你能够很容易地解决这个问题git commit --amend。这将添加从上次提交到暂存区域的全部内容,并尝试进行新的提交。这给你一个机会来解决你的提交信息或添加更多的文件到临时区域。
对于不在上次提交中的更复杂的修复(或者若是您已经推送了更改),则必须使用git revert。 这将采起提交引入的全部更改,将其回滚,并建立一个与此相反的新提交。
最新的提交能够被HEAD别名访问。
$ git revert HEAD
对于其余提交,最好使用一个id。 $ git revert b10cc123
当恢复较旧的提交时,请记住合并冲突极可能会出现。 当一个文件被另外一个更近的提交改变时,会发生这种状况,如今Git找不到正确的行来恢复,由于它们不在那里了。
除了前面所描述的状况以外,在合并分支或者牵扯其余人的工做时常常出现冲突。 有时候,冲突是由git自动处理的,但有时候处理这些冲突的人必须决定(一般是精选)哪些代码保留,什么被删除。
咱们来看一个例子,我会合并两个叫作john_branch和tim_branch的分支。 小张和小李都在同一个文件中写入一个显示数组中全部元素的函数。
小张正在使用for循环:
//使用for循环到console.log内容。
for(var i = 0;
i
<
arr
.
length
;
i
++){
console
.
log
(
arr
[
i
]);
}
小李喜欢
forEach
:
//使用forEach到console.log内容。
arr
.
forEach
(
function
(
item
)
{
console
.
log
(
item
);
});
他们都在各自的分支上提交代码。
如今,若是他们尝试合并两个分支,他们将看到如下错误消息:
$ git merge tim_branch
Auto
-
merging print_array
.
js
CONFLICT
(
content
):
Merge
conflict
in
print_array
.
js
Automatic
merge failed
;
fix conflicts
and
then
commit the result
.
复制代码
Git没法自动合并分支,因此如今由开发人员手动解决冲突。 若是他们打开冲突所在的文件,他们会看到Git在冲突的行上插入了一个标记。
<<<<<<< HEAD
// Use a for loop to console.log contents.
for(var i=0; i
<arr.length
;
i
++) {
console
.
log
(
arr
[
i
]);
}
======
=
//
Use
forEach
to
console
.
log
contents
.
arr
.
forEach
(
function
(
item
) {
console
.
log
(
item
);
});
>
>>>>>> xiaozhang's commit. 复制代码
在=====之上,咱们有当前的HEAD提交,而且在冲突之下。 这样咱们就能够清楚地看到差别,并决定哪一个版本更好,或者一块儿写一个新版本。 在这种状况下,咱们去找后者,重写整个事情,删除标记让Git知道咱们已经完成了。 //不使用循环或forEach。 //将Array.toString()用于console.log内容。 console . log ( arr . toString ());
m "解决冲突." 正如你所看到的,这个过程很是烦人,在大型项目中可能会遇到很大的困难。 大多数开发人员倾向于在GUI客户端(下载https://git-scm.com/download/gui/linux) 的帮助下解决冲突,这使事情变得更容易。运行图形客户端使用git mergetool。
在大多数项目中都有咱们不想提交的文件或整个文件夹。 咱们能够git add -A 经过建立.gitignore文件来确保它们不会被意外地包含在咱们 的内容中: 手动建立一个名为.gitignore的文本文件,并将其保存到项目目录中。 在里面,列出要忽略的文件/目录的名称,每一个都在一个新的行上。 .gitignore自己必须被添加,提交和推送,就像项目中的任何其余文件同样。 很好的文件被忽略的例子是: 日志文件 任务运行者创建 node.js项目中的node_modules文件夹 由NetBeans和IntelliJ等IDE建立的文件夹 我的开发者笔记
禁止上述全部内容的.gitignore将以下所示: *.
log
build
/
node_modules
/
.
idea
/
my_notes
.
txt
复制代码
在某些行末尾的斜线表示这是一个文件夹,咱们忽略了递归中的全部内容。星号一般用做通配符。
Git至关复杂,并提供更多的功能和技巧。若是你想了解更多 推荐的学习资源: 官方的Git文档,包括一整本书和视频课程 -在这里(git-scm.com/doc)。 让git正确 - Atlassian收集的教程和文章 -在这里(www.atlassian.com/git/)。 一个GUI客户端列表 -在这里(www.git-scm.com/downloads/g… Git备忘单(PDF) -这里。 services.github.com/on-demand/d…
生成.gitignore文件的在线工具 -在这里。 www.gitignore.io/