Git 近年来受到欢迎。版本代码控制系统被 Linux 等巨大的开源项目所使用,成千上万的贡献者,各种规模的团队,独立开发者,甚至是学生。
Git 近年来受到欢迎。版本代码控制系统被 Linux 等巨大的开源项目所使用,成千上万的贡献者,各种规模的团队,独立开发者,甚至是学生。
初学者常常被 git 所要求的所有神秘的命令和参数所吓倒。之前一篇文章不够全面 10 个有用的 Git 命令提示 。但是你不需要知道所有这些就可以开始使用它。你可以开始掌握一些最常用的,然后从在慢慢进一步学习。
这正是我们今天要教给你的。让我开始今天的正文!
Git 是一个命令行实用程序的集合,它会跟踪和记录文件中的更改(通常是源代码,但是可以跟踪任何你想要的文件)。
有了它,您可以恢复项目的旧版本,比较,分析,合并更改等操作。
这个过程被称为版本控制。
有许多版本控制系统可以完成这项工作。
你可能听说过其中的一些 --SVN,Mercurial,Perforce,CVS,Bitkeeper 等等。
Git 是分散的,这意味着它不依赖于中央服务器来保留文件的旧版本。
相反,它完全在本地运行,将这些数据作为一个文件夹存储在硬盘上,我们称之为储存仓库。
但是,你也可以在线存储您的仓库的副本,这使得多个人可以轻松协作并使用相同的代码。这就是像 GitHub 和 BitBucket 这样的网站所使用的一样。
在你的设备上安装 Git 很简单:
sudo apt - get install git
brew install git
从终端运行。如果你是一个绝对的初学者,那么一个图形化的 git 客户端是必须的。
我强烈推荐使用 GitHub Desktop 和 Sourcetree,但是还有许多其他好的和免费的在线。
即使使用 GUI 应用程序,了解基本的 git 命令仍然很重要,因此在本文剩下的部分中,这将是我们唯一说的重点。
现在我们已经在我们的计算机上安装了 git,我们将需要添加一些快速配置。
有很多可以摆弄的选项,但是我们要设置最重要的选项:我们的用户名和电子邮件。
打开一个终端并运行这些命令:
$ git config --global user.name "My Name"
$ git config --global user.email myEmail@example.com
我们在 Git 中所做的每一个动作现在都会贴上我们的名字和地址。
这样用户总是知道谁做了什么,一切都更有条理。
正如我们前面提到的,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 文件夹中。
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 不知道它是否应该跟踪发生在这个文件上的变化,或者忽略它。为了确认新文件,我们需要对其进行分类。
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
。一个提交表示在给定的时间点我们的仓库的状态。这就像一个日志记录,我们可以回顾一下,看看我们拿什么。
要创建一个新的提交,我们需要至少有一个更改添加到暂存区域(我们这样做
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 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
这只是创建了新的分支,在这一点上是完全一样的,我们的主干。
现在,当我们运行时
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
在本文的最后一节中,我将介绍一些更高级的技术,这些技术很可能在你工作中派上用场。
每个提交都以数字和符号的字符串形式存在唯一的 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 的分支。
John 和 Tim 都在同一个文件中写入一个显示数组中所有元素的函数。
John 正在使用 for 循环:
//使用for循环到console.log内容。
for(var i = 0 ; i <arr.length; i ++){
console .log(arr [i]);
}
Tim 喜欢 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; i++) {
console.log(arr[i]);
}
=======
// Use forEach to console.log contents.
arr.forEach(function(item) {
console.log(item);
});
>>>>>>> Tim's commit.
在 ===== 之上,我们有当前的 HEAD 提交,并且在冲突之下。
这样我们就可以清楚地看到差异,并决定哪个版本更好,或者一起写一个新版本。
在这种情况下,我们去找后者,重写整个事情,删除标记让 Git 知道我们已经完成了。
//不使用循环或forEach。
//将Array.toString()用于console.log内容。
console.log(arr.toString());
当所有东西都被设置好后,就必须完成一个合并提交来完成这个过程。
$ git add -A
$ git commit -m "解决冲突."
正如你所看到的,这个过程非常烦人,在大型项目中可能会遇到很大的困难。
大多数开发人员倾向于在 GUI 客户端(下载 https://git-scm.com/download/gui/linux)
的帮助下解决冲突,这使事情变得更容易。运行图形客户端使用 git mergetool。
在大多数项目中都有我们不想提交的文件或整个文件夹。
我们可以 git add -A 通过创建. gitignore 文件来确保它们不会被意外地包含在我们
的内容中:
很好的文件被忽略的例子是:
禁止上述所有内容的. gitignore 将如下所示:
*.log
build/
node_modules/
.idea/
my_notes.txt
在某些行末尾的斜线表示这是一个文件夹,我们忽略了递归中的所有内容。星号通常用作通配符。
这结束了我们的教程在 git!
我尽最大的努力为您提供您所需要的最重要的学习信息,我觉得已经是最简洁明了。
Git 相当复杂,并提供更多的功能和技巧。如果你想了解更多,这里有一些我们推荐的学习资源:
作者:Tamic
英文作者:Danny Markov
https://tutorialzine.com/2016/06/learn-git-in-30-minutes
面试资料免费获取请回复 "面试资料",学习更多请回复 "学习"
开发者技术前线 汇聚最新最热的技术干货,
行业动态,职场思考, 热点思维,和一线面经!
来源: http://mp.weixin.qq.com/s/BJXmZOZlZmhIzi6_-smyrg