目录
扩展名为.pyc的文件是根据.py文件自动生成的,因此我们无需让Git跟踪它们。这些文件存 储在目录__pycache__中。为让Git忽略这个目录,创建一个名为.gitignore的特殊文件(这个文件 名以句点打头,且没有扩展名),并在其中添加下面一行内容:
.gitignore
__pycache__/
这让Git忽略目录__pycache__中的所有文件。使用文件.gitignore可避免项目混乱,开发起来 更容易。
如果你使用的是Python 2.7,请将这行内容改为*.pyc。Python 2.7不会创建目录 __pycache__,它将每个.pyc文件都存储在相应.py文件所在的目录中。其中的星号让Git 忽略所有扩展名为.pyc的文件
你可能需要修改文本编辑器的设置,使其显示隐藏的文件,这样才能使用它来打开文 件.gitignore。有些编辑器被设置成忽略名称以句点打头的文件。
你创建了一个目录,其中包含一个Python文件和一个.gitignore文件,可以初始化一个Git仓库 了。为此,打开一个终端窗口,切换到文件夹git_practice,并执行如下命令:
git_practice$ git init
Initialized empty Git repository in git_practice/.git/
git_practice$
输出表明Git在git_practice中初始化了一个空仓库。仓库是程序中被Git主动跟踪的一组文件。 Git用来管理仓库的文件都存储在隐藏的.git/中,你根本不需要与这个目录打交道,但千万不要删 除这个目录,否则将丢弃项目的所有历史记录。
执行其他操作前,先来看一下项目的状态
git_practice$ git status
1 # On branch master
#
# Initial commit
#
2 # Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# .gitignore
# hello_world.py
#
3 nothing added to commit but untracked files present (use "git add" to track)
git_practice$
在Git中,分支是项目的一个版本。从这里的输出可知,我们位于分支master上(见1)。你 每次查看项目的状态时,输出都将指出你位于分支master上。接下来的输出表明,我们将进行初 始提交。提交是项目在特定时间点的快照。 Git指出了项目中未被跟踪的文件(见2),因为我们还没有告诉它要跟踪哪些文件。接下来, 我们被告知没有将任何东西添加到当前提交中,但我们可能需要将未跟踪的文件加入到仓库中 (见3)。
下面将这两个文件加入到仓库中,并再次检查状态:
1 git_practice$ git add .
2 git_practice$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
3 # new file: .gitignore
# new file: hello_world.py
#
git_practice$
命令git add .将项目中未被跟踪的所有文件都加入到仓库中(见1)。它不提交这些文件, 而只是让Git开始关注它们。现在我们检查项目的状态时,发现Git找出了需要提交的一些修改(见 2)。标签new file意味着这些文件是新添加到仓库中的(见3)。
下面来执行第一次提交:
1 git_practice$ git commit -m "Started project."
2 [master (root-commit) c03d2a3] Started project.
3 2 files changed, 1 insertion(+)
create mode 100644 .gitignore
create mode 100644 hello_world.py
4 git_practice$ git status
# On branch master
nothing to commit, working directory clean
git_practice$
我们执行命令git commit -m "message"(见1)以拍摄项目的快照。标志-m让Git将接下来的 消息("Started project.")记录到项目的历史记录中。输出表明我们在分支master上(见2), 且有两个文件被修改了(见3)。 现在我们检查状态时,发现我们在分支master上,且工作目录是干净的(见4)。这是你每次 提交项目的可行状态时都希望看到的消息。如果显示的消息不是这样的,请仔细阅读,很可能你 在提交前忘记了添加文件。
Git记录所有的项目提交。下面来看一下提交历史:
git_practice$ git log
commit a9d74d87f1aa3b8f5b2688cb586eac1a908cfc7f
Author: Eric Matthes <eric@example.com>
Date: Mon Mar 16 07:23:32 2015 -0800
Started project.
git_practice$
你每次提交时,Git都会生成一个包含40字符的独一无二的引用ID。它记录提交是谁执行的、 提交的时间以及提交时指定的消息。并非在任何情况下你都需要所有这些信息,因此Git提供了 一个选项,让你能够打印提交历史条目的更简单的版本:
git_practice$ git log --pretty=oneline
a9d74d87f1aa3b8f5b2688cb586eac1a908cfc7f Started project.
git_practice$
标志--pretty=oneline指定显示两项最重要的信息:提交的引用ID以及为提交记录的消息。
为展示版本控制的强大威力,我们需要对项目进行修改,并提交所做的修改。为此,我们在 hello_world.py中再添加一行代码:
hello_world.py
print("Hello Git world!")
print("Hello everyone.")
如果我们现在查看项目的状态,将发现Git注意到了这个文件发生了变化:
git_practice$ git status
1 # 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)
#
2 # modified: hello_world.py
#
3 no changes added to commit (use "git add" and/or "git commit -a")
git_practice$
输出指出了我们当前所在的分支(见1)、被修改了的文件的名称(见2),还指出了所做的 修改未提交(见3)。下面来提交所做的修改,并再次查看状态:
1 git_practice$ git commit -am "Extended greeting."
[master 08d4d5e] Extended greeting.
1 file changed, 1 insertion(+)
2 git_practice$ git status
# On branch master
nothing to commit, working directory clean
3 git_practice$ git log --pretty=oneline
08d4d5e39cb906f6cff197bd48e9ab32203d7ed6 Extended greeting.
be017b7f06d390261dbc64ff593be6803fd2e3a1 Started project.
git_practice$
我们再次执行了提交,并在执行命令git commit时指定了标志-am(见1)。标志-a让Git将仓 库中所有修改了的文件都加入到当前提交中(如果你在两次提交之间创建了新文件,可再次执行 命令git add .将这些新文件加入到仓库中)。标志-m让Git在提交历史中记录一条消息。 我们查看项目的状态时,发现工作目录也是干净的(见2)。最后,我们发现提交历史中包 含两个提交(见3)。
下面来看看如何放弃所做的修改,恢复到前一个可行状态。为此,首先在hello_world.py中再 添加一行代码:
hello_world.py
print("Hello Git world!")
print("Hello everyone.")
print("Oh no, I broke the project!")
保存并运行这个文件。 我们查看状态,发现Git注意到了所做的修改:
git_practice$ 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)
#
1 # modified: hello_world.py
#
no changes added to commit (use "git add" and/or "git commit -a")
git_practice$
Git注意到我们修改了hello_world.py(见1)。我们可以提交所做的修改,但这次我们不提交 所做的修改,而要恢复到最后一个提交(我们知道,那次提交时项目能够正常地运行)。为此, 我们不对hello_world.py执行任何操作——不删除刚添加的代码行,也不使用文本编辑器的撤销功能,而在终端会话中执行如下命令:
git_practice$ git checkout .
git_practice$ git status
# On branch master
nothing to commit, working directory clean
git_practice$
命令git checkout让你能够恢复到以前的任何提交。命令git checkout .放弃自最后一次提 交后所做的所有修改,将项目恢复到最后一次提交的状态。 如果我们返回到文本编辑器,将发现hello_world.py被修改成了下面这样:
print("Hello Git world!")
print("Hello everyone.")
就这个项目而言,恢复到前一个状态微不足道,但如果我们开发的是大型项目,其中数十个 文件都被修改了,那么恢复到前一个状态,将撤销自最后一次提交后对这些文件所做的所有修改。 这个功能很有用:实现新功能时,你可以根据需要做任意数量的修改,如果这些修改不可行,可 撤销它们,而不会对项目有任何伤害。你无需记住做了哪些修改,因而不必手工撤销所做的修改, Git会替你完成所有这些工作。
想要看到以前的版本,你可能需要在编辑器窗口中单击,以刷新文件。
D.11 检出以前的提交
你可以检出提交历史中的任何提交,而不仅仅是最后一次提交,为此可在命令git check末 尾指定该提交的引用ID的前6个字符(而不是句点)。通过检出以前的提交,你可以对其进行审核, 然后返回到最后一次提交,或者放弃最近所做的工作,并选择以前的提交:
git_practice$ git log --pretty=oneline
08d4d5e39cb906f6cff197bd48e9ab32203d7ed6 Extended greeting.
be017b7f06d390261dbc64ff593be6803fd2e3a1 Started project.
git_practice$ git checkout be017b
Note: checking out 'be017b'.
1 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 commits 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.
git_practice$
检出以前的提交后,你将离开分支master,并进入Git所说的分离头指针(detached HEAD) 状态(见1)。HEAD表示项目的当前状态,之所以说我们处于分离状态,是因为我们离开了一个 命名分支(这里是master)。 要回到分支master,可检出它: