Git—版本控制

版本控制软件让你能够拍摄处于可行状态的项目的快照。修改项目后,如果新修改后的项目不能正常运行,可恢复到前一个可行状态。
通过使用版本控制软件,可以无忧无虑地改进项目,不用担心项目因你犯了错而遭到破坏。对大型项目来说,这是非常重要的。
Git是当前最流行的版本控制软件,它包含很多高级工具,可帮助团队协作开发大型项目,但其最基本的功能也非常适合独立开发人员使用。Git通过跟踪对项目中给每个文件的修改来实现版本控制,如果犯错了,只需要恢复到保存的前一个状态即可。

1.安装Git

Git可在所有操作系统上运行,只是在安装方法上面不同的操作系统有些差异。

1.1在Linux系统中安装Git

要在Linux系统中安装Git,执行如下命令即可:

$sudo apt-get install git

1.2在OS X系统中安装Git

有的OS X系统中可能已经安装了Git,在命令行中输入git --version进行确认。如果你在输出中看到了具体的版本号,说明系统中安装了Git;如果有提示安装或者升级Git,安装屏幕上的步骤操作即可。
也可以访问https://git-scm.com/,单击链接Downloads下载。

1.3在Windows系统中安装Git

在windows中安装Git,可以访问http://msysgit.github.io/,然后点击Download下载安装即可。

1.4配置Git

Git跟踪谁修改项目,哪怕参与项目开发的人只有一个。为此,Git需要知道你的用户名和电子邮件地址。所以必须提供用户名,但可以使用虚构的电子邮件地址:

$git config --global user.name "username"
$git config --global user.email "username%example.com"

比如:
在这里插入图片描述
如果忘记了这一步,在首次提交时,Git将提示你提供这些信息。

2.创建项目

接下来我们就创建一个要进行版本控制的项目。操作系统呢,是windows系统。首先找到一个合适的目录,然后创建一个文件夹,并将其命名为git_practice。在这个文件夹中,创建一个简单的Python程序:
在这里插入图片描述
在这里插入图片描述
hello_world.py

print("Hello Git world!")

在这里插入图片描述
接下来我们就是用这个例子来学习一下Git的基本使用功能。

3忽略文件

扩展名为.pyc的文件是根据.py文件自动生成的,因此我们无需让Git跟踪它们。这些文件存储在目录__pycache__中。为让Git忽略这个目录,创建一个名为.gitignore的特殊文件(这个文件名以句点打头,且没有扩展名),并在其中添加下面一行内容:
.gitignore

__pycache__/

在这里插入图片描述
在这里插入图片描述
这让Git忽略目录__pycache__中的所有文件。使用文件.gitignore可避免项目混乱,开发起来更容易。
注意:如果使用的是python2.7,请将这行内容改为.pyc.。python2.7不会创建目录__pycache__,它将每个.pyc文件都存储在相应.py文件所在的目录中。其中的星号让Git忽略所有扩展名为.pyc的文件。*
你可能需要修改文本编辑器的设置,使其显示隐藏的文件,这样才能使用它来打开文件.gitignore。有些编辑器被设置成忽略名称以句点打头的文件。

4.初始化仓库

你创建一个目录,其中包括一个Python文件和一个.gitignore文件,可以初始化Git仓库了。为此,打开一个终端窗口,切换到文件夹git_practice,并执行如下命令:
在这里插入图片描述
输出表明Git在git——practice中初始化了一个空仓库。仓库是程序中被Git主动跟踪的一组文件。Git用来管理仓库的文件都存储在隐藏的.git/中,我们根本不需要与这个目录打交道,但千万不要删除这个目录,否则将丢弃项目的所有历史记录。
在这里插入图片描述
当然命令git init是把当前所在的文件夹初始化为仓库,我们也可以初始化一个指定的仓库,就是在命令git init后面输入目录名字,比如:

$git init git_pratice

首先创建一个目录。
在这里插入图片描述
然后初始化这个目录为仓库,在init后面跟上目录的名字:
在这里插入图片描述
进入目录,查看:
在这里插入图片描述
查看仓库状态:
在这里插入图片描述
然后我们进入其他的目录看看怎么在当前目录初始化不再当前目录的目录为仓库:
在这里插入图片描述
在这里插入图片描述
当前目录里面没有git_pratice目录,在当前目录的上一级目录里面有git_prctice目录,explme目录和git_pratice是同一级的目录,不是父子目录的关系,那怎么初始化git_practice目录为仓库呢?可不可以和上面一样直接使用命令呢?我们试试看看是什么样的结果:
在这里插入图片描述
然后我们看一当前的explme目录有没有什么变化:
在这里插入图片描述
git init后竟然是直接在explme目录直接创建一个git_pratice目录为仓库,而不是初始化上一级目录中的git_pratice目录为仓库,所以这样直接跟目录名字的方式是,如果当前所在的路径目录下有输入的目录,就初始化为仓库,如果不存在输入的目录,就创建目录,并初始化为仓库。
既然这样不行我们就试试另一种方式,我们知道在命令行目录跳转时,可以通过指定相对路径和绝对路径,那我们就试试相对路径的方式吧:
在这里插入图片描述
我们再看一下explme目录下有没有新添加目录:
在这里插入图片描述
我们看没有新添加目录,那我们在看看上一级目录里的git_pratice目录是不是被初始化为仓库了
在这里插入图片描述
在这里插入图片描述
已经初始化为仓库了,绝对路径也是一样的效果,有兴趣的小伙伴,可以试试绝对路径的初始化仓库的方式哦。

5.检查状态

执行其他操作前,先来看一下项目的状态:

$git status
#On branch master   ----<1
#
# Initial commit
#
#Untracked files:  ----<2
#	(Use "git add <file>..." to include in what will be committed)
#    .gitignore
#     hello_world.py
#
nothing added to commit but untracked files present (use "git add" to track)  ----<3

在这里插入图片描述
在Git中,分支是项目的一个版本。从这里的输出可知,现在位于分支master上(见1).每次查看项目的状态时,输出都将指出你位于分支master上。接下来的输出表明,我们将进行初始提交。提交是项目在特定时间点的快照。
Git指出了项目中未被跟踪的文件(见2),因为我们还没有告诉它要跟踪那些文件。接下来,我们被告知没有将任何东西添加到当前提交中,但我们可能需要将未跟踪的文件加入到仓库中(见3).

将文件加入到仓库中

下面将这两个文件加入到仓库中,并再次检查状态:

$git add .   ----<1
$git status  ----<2
#On branch master
#
#Initial commit
#
#Changes to be committed:
#	(use "git rm --cached <file>..." to unstage)
#	new file: .gitignore   ----<3
#	new file: hello_world.py
#

在这里插入图片描述
命令git add .将项目中未被跟踪的所有文件都加入到仓库中。它不提交这些文件,而只是让Git开始关注它们。现在我们检查项目的状态时,发现Git找出了需要提交的一些修改(见2).标签new file意味着这些文件是新添加到仓库中的(见3)

7.执行提交

下面来执行第一次提交:

$git commit -m "Started project."    ----<1
[master (root-commit) c03d2a3] Started project.   ----<2
2 files changed, 1 insertion(+)         ----<3
create mode 100644 .gitingore
create mode 100644 hello_world.py
$git status    ----<4
#On branch master
nothing to commit, working directory clean

在这里插入图片描述
我们执行命令git commit -m “message”(见1)以拍摄项目的快照。标志-m让Git将接下来的消息(“Started project.”)记录到项目的历史记录中。输出表明我们在分支master上(见2),且有两个文件被修改了(见3)。
现在我们检查状态时,发现我们在分支master上,且工作目录是干净的(见4).这是你每次提交项目的可行状态时都希望看到的消息。如果显示的消息不是这样的,请仔细阅读,可能你在提交前忘记了添加文件。

8.查看提交历史

Git记录所有的项目提交。下面来看一下具体的提交历史:

$git log
commit a9d74d--------fc7f
Author: Eric Matthes <eric@example.com>
Date: Mon Mar 16 07:23:32 2015 -0800

	Started project

在这里插入图片描述
每次提交时,Git都会生成一个包含40字符的独一无二的引用ID。它记录提交是谁执行的、提交的时间以及提交时指定的消息。并非在任何情况下都需要所有这些消息,因此Git提供了一个选项,让你能够打印提交历史条目的更简单的版本:

$git log --pretty=oneline
a9d74d--------fc7f Started project.

在这里插入图片描述
标志–pretty=oneline指定显示两项最重要的信息:提交的引用ID以及为提交记录的消息。

9.第二次提交

为展示版本控制的强大之处,接下来对项目进行修改并提交所作的修改。在创建的hello_world.py中再添加一行代码:

print("Hello Git world!")
print("Hello everyone.")

如果我们现在查看项目的状态,将发现Git注意到了这个文件发生了变化:

$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: .hello_world.py
#
no changes added to commit (use "git add" and /or "git commit -a")

在这里插入图片描述
输出指出了当前所在分支、被修改了的文件的名称,还指出了所作的修改未提交。下面来提交所做的修改,并再次查看状态:

$git commit -am "Extended greeting."
[master 08d4d5e] Extended greeting.
 1 file changed, 1 insertion(+)
 $git status
 #On branch master
 nothing to commit,working directory clean
 $git log --pretty=oneline
 08d4d5e--------7ed6 Extended greeting.
 be017b7f--------2e3a1 started project.

在这里插入图片描述
我们再次执行了提交,并在执行命令git commit时指定了标志**-am**。标志**-a让Git将仓库中所有修改了的文件都加入到当前提交中(如果你在两次提交之间创建了新文件,可再次执行命令git add .** ,将这些新文件加入到仓库中)。标志**-m**让Git在提交历史中记录一条消息。
我们查看项目的状态时,发现工作目录也是干净的。最后,我们发现提交历史中包含两个提交。

10比较新修改的文件增加了那些代码

我们有时想知道部分新提交的文件都修改了那些,看看修改后的文件变动大吗等等,可以使用Git的diff命令,如下:
在这里插入图片描述
输出的结果以a,b两个文件来表示,然后使用—和+++来表示减少和增加的部分。

11撤销修改

下面来看看如何放弃所做的修改,恢复到前一个可行状态。为此,首先在hello_world.py中再添加一行代码:

print("Hello Git world!")
print("Hello everyone.")

print("Oh no,I broke the project!")

我们查看状态,发现Git注意到了所做的修改:

$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: .hello_world.py
#
no changes added to commit (use "git add" and /or "git commit -a")

Git 注意到我们修改了hello_world.py,我们可以提交所做的修改,但这次我们不提交所做的修改,而要恢复到最后一个提交(上次提交时项目能够正常地运行)。为此,我们不对hello_world.py执行任何操作------不删除刚添加的代码行,也不使用文本编辑器的撤销功能,而在终端会话中执行如下命令:

$git checkout .
$git status
 #On branch master
 nothing to commit,working directory clean

在这里插入图片描述
然后我们在看一下我们刚才修改文件有没有什么变化:
在这里插入图片描述
点击是以后,我们之前新修改的一行没有了:
在这里插入图片描述
命令git checkout让你能够恢复到以前的任何提交。命令**git checkout .**放弃自最后一次提交后所做的所有修改,将项目恢复到最后一次提交的状态。
如果我们返回到编辑器,将发现hello_world.py会恢复到上面的情景。
就这个项目而言,恢复到前一个状态微不足道,但如果我们开发的是大型项目,其中数十个文件都被修改了,那么恢复到前一个状态,将撤销自最后一次提交对这些文件所做的所有修改。这个功能很有用:实现新功能时,你可以根据需要做任意数量的修改,如这些修改不可行,可撤销它们,而不会对项目有任何伤害。我们无需记住做了那些修改,因而不必手工撤销所作的修改,Git会替我们完成所有这些工作。

12检出以前的提交

我们可以检出提交历史中的任何提交,而不仅仅是最后一次提交,为此可在命令git check末尾指定该提交的引用ID的前6个字符(不是句点了,是提交历史中某一次的前6个字符)。通过检出以前的提交,你可以对其进行审核,然后返回到最后一次提交,或者放弃最近所作的工作,并选择以前的提交:

 $git log --pretty=oneline
 08d4d5e--------7ed6 Extended greeting.
 be017b7f--------2e3a1 started project.
 $git checkout be017b
 Note: checking out 'be017b'
You are in 'detached HEAD' state.You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout.

If you want to create a new branch to retain comits you create, you may do so(now or later) by using -b with the checkout command again, Example:

	git checkout -b new_branch_name
HEAD is now at be017b7... Started project.

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
检出以前的提交后,我们将离开分支master,并进入Git所有的分离头指针(detached HEAD)状态。HEAD表示项目的当前状态,之所以说我们处于分离状态,是因为我们离开了一个命名分支(这里是master)。
在这里插入图片描述
要回到分支master,可检出它:

$git checkout master
Previous HEAD position was be017b7... Started project.
Switched to branch 'master'

在这里插入图片描述
之前的提交的两次还都存在,那我们在checkout出最后一次提交的信息
看checkout出master以后我们又把最后一次提交的信息给检出来了。
回到分支master。除非我们要使用Git的高级功能,否则在检出以前的提交后,最好不要对项目最任何修改。然而,如果参与项目开发的人只有你自己,而你又想放弃较近的所有提交,并恢复到以前的状态,也可以将项目重置到以前的提交。为此,可在处于分支master上的情况下,执行如下命令:
在这里插入图片描述
我们首先查看了状态,确认我们在分支master上。查看提交历史时,我们看到了两个提交。接下来,我们执行命令git reset --hard,并在其中指定了要永久地恢复到的提交的引用ID的前6个字符。再次查看状态,发现我们在分支master上,且没有需要提交的修改。再次查看提交历史时,发现我们处于要从它重新开始的提交中。
在这里插入图片描述
这次我们永久的恢复到了提一次提交的文件:
在这里插入图片描述

13 删除仓库

有时候,仓库历史记录被搞乱了,而我们又不知道如何恢复。如果无法恢复且参与项目开发的只有你一个人,可继续使用这些文件,但要将项目的历史记录删除------删除目录.git.这不会影响任何文件的当前状态,而只会删除所有的提交,因此你将无法检出项目的其他任何状态。
为此,可打开一个文件浏览器,并将目录.git删除。也可通过命令行完成这个任务。这样做后,我们需要重新创建一个仓库,以重新对修改进行跟踪。比如:
在这里插入图片描述
然后重新初始化仓库:
在这里插入图片描述
首先我们查看了状态,工作目录时干净的,接下来我们使用命令rm -rf .git(在windows系统中,应使用命令rmdir /s .git)删除目录.git。删除文件夹.git后。当我们再次查看状态时,被告知这不是一个.git仓库。Git用来跟踪仓库的信息都存储在文件夹.git中,因此删除该文件夹也将删除整个仓库。
接下来我们使用命令git init新建一个全新的仓库,然后,我们查看状态,发现又回到了最初的状态,等待第一次提交。我们将所有文件都加入仓库,并执行第一次提交,然后再次查看状态,发现我们在分支master上,且没有任何未提交的修改。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐