Git——常用基本操作
获取仓库
Git有两种方式可以获取Git仓库(repository):1.在本地现有目录或项目下将文件加入到Git中;2.从服务器上克隆一个已存在的Git仓库。
1.如果你想将一个本地目录或项目使用Git进行管理,需要在该根目录下使用如下命令:
git init
这条命令会生成一个名为.git的子目录;它包含了我们初始化的Git仓库中所有的必须文件,这些文件是Git仓库的主要内容。此时,我们仅仅是初始化了Git仓库,而没有对其中的工程文件做追踪。
2.我们还可以从服务器上克隆一个已经存在的Git仓库:
git clone [url]
Git克隆的是该Git仓库在服务器上的几乎所有数据,而不仅仅是你需要完成工作的那些工程文件。默认配置下,Git clone会将服务器上该工程下的每个文件的每个版本都拉取下来。例如:
git clone https://github.com/code/code
这会在当前目录下创建一个名为"code"的目录,并在此目录下初始化一个.git文件夹,从远程仓库拉取所有数据放入.git文件夹,然后从中读取最新版的文件的拷贝。进入到code目录,我们会发现所有的项目文件已经都在里面了,准备就绪等待开发和使用。
如果我们向在克隆仓库的时候,自定义本地仓库的名字,可以这样做:
git clone https://github.com/code/code mycode
这样在本地创建的仓库名字就变为mycode了。
现在我们已经有了一个项目的真实Git仓库,并从这个仓库中取出了所有文件的拷贝。接下来,对这些文件进行修改,并当我们完成了一个阶段性目前后,提交本次更新到仓库;这样其他人就可以同步你的修改了。
需要明确的一点是,工作目录下的每个文件都只有两种状态:已跟踪或未跟踪。已跟踪的文件是指那些被纳入了版本控制的文件,上一次快照中有它们的记录。在工作一段时间后,它们的状态可能会发生改变,处于未修改、已修改或已暂存。工作目录中中除已跟踪文件外的所有其他文件都是属于未跟踪文件,即它们不在Git版本控制之下;它们既不存在于上次的快照记录中,也没有放入暂存区。除此克隆某个仓库的时候,工作目录中的所有文件都处于已跟踪、未修改状态。
在上次提交之后,我们编辑过某些文件,那它们将被标记为已修改文件。我们会将这些改动的文件放入暂存区,然后提交所有暂存了的改动。
查看状态
如果我们要查看当前文件的状态,可以使用
git status
命令,如果我们的工作目录在克隆下来之后,未做任何修改,将看到这样的输出:
如果我们做了修改,如创建了README文件;在运行此命令,此时则会看到如下内容:
Git指出README文件未被追踪,即它在Git上一次提交的快照在宏不存在。如果我们想跟踪README文件,必须手动明确指出,这样会让你不必担心将生成的二进制文件或其他不需要被跟踪的文件包括进来。
追踪文件
为了跟踪README文件,我需要执行
git add
命令:
使用git add开始跟踪一个文件;再次运行git status命令会看到README文件已经被跟踪,并处于暂存状态。
显示在"Changes to be commited"之下的文件都处于暂存状态。这时如果我们提交,那此刻的版本将被留存在历史记录中。git add命令可以使用文件列表或目录路径作为参数。使用文件列表,表明要跟踪明确指出的这些文件;使用路径名,表示要循环递归跟踪此路径下的所有文件。
如果我们修改了一个已经被跟踪的文件,如LOGFILE,再运行git status则会看到如下内容:
LOGFILE文件出现在Changes not staged for commit下面,这表明之前一个已被跟踪的文件的内容发生了变化,但还没有暂存到缓冲区。要暂存这次更新,需要重新对它执行git add命令。git add命令既可以开始跟踪一个新文件,也可以把已跟踪的文件放到暂存区,还能用于合并时把冲突的文件标记为已解决状态。
git add的用意我们就可以认为是“添加内容到下一次提交中”;将LOGFILE添加到暂存区中,再看git status输出:
git add只会暂存你运行该命令之后的文件版本。
查看文件修改
git status只会显示出哪些文件被改动了,但如果我们想看到具体改了什么,就需要使用
git diff
命令:
git diff命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。
若要查看已暂存的,在下次会被提交的内容差异,可以使用加--staged参数
git diff --staged
因为README、LOGFILE文件都是新建、并加入内容的,所以看到的输出如上所示。
还是要注意:git diff只显示尚未暂存的改动,而不是自上次提交以来所做的改动。所以,当我们暂存了所以已修改的文件后,git diff就不会显示任何差异了。
有时候,我们需要查看两次版本提交之间的差异信息,这也可以使用git diff完成:
git diff commitID commitID
如:
提交修改
我们对文件完成修改、暂存之后,就可以进行提交了:
git commit命令可以提交之前所有暂存的修改。直接使用git commit命令后,会根据之前的配置弹出填写提交记录的文本编辑器。笔者配置的是gedit,所以这里弹出的就是gedit框。默认的提示消息包含最后一次执行git status的内容。其中的注释内容都是可以删掉、编辑的。退出编译器,Git会跳过注释行,只以你的提交信息生成一次提交。
输入需要填写的commit message并保存,一次提交就完成了:
输入git log查看一下我们的提交记录,根据输出可以看到我们提交信息为“test commit”的这次提交。
给Git commit 加上-m参数,可以直接指定提交信息,而不用在编辑器中输入:
git commit -m "test commit"
直接使用git commit可以让我们跳过之前的git add操作,只需加上-a参数即可。Git就会自动把所有已经跟踪过的文件暂存起来一并提交,包括文件修改和文件删除;如果,我们新创建了一个文件,但没有追踪它,-a参数也不会提交它。
git commit -a -m "test commit"
注意,对于新建文件,还是请先使用git add操作进行暂存。
文件修改、文件暂存、查看状态、查看差异、提交暂存,是我们使用Git时最常使用的操作,熟悉这些基本就可以简单进行我们的业务管理了。
移除/改名文件
如果需要从Git中移除一个文件,就必须把该文件从已跟踪清单文件(即暂存区)中移除,然后提交。
git rm
命令可以完成此操作;并连带从工作目录中删除指定的文件,这样这个文件就不会在未跟踪清单中出现了。
如果直接在工作目录删除一个文件,我们看下结果:
我们删掉了LOGFILE文件,git status之后发现它出现在了未跟踪清单文件中。我们再使用
git rm
命令:
这样,我们如果提交这次更新,LOGFILE文件就不会再纳入版本管理了。
有些时候,我们想让移除一个文件,让它不再被Git管理;但想保留本地文件,这时,我们可以使用参数完成:
git rm --cached LOGFILE
如果想移除多个文件或某个文件夹,则在命令后面添加文件列表(空格隔开)或使用目录路径即可。如果删除已经被修改、存入暂存区(但未提交)的文件时,需要使用-f选项,不然会报错;这是用于防止误删还未添加到快照的文件的手段。
在git中如果要对文件改名,我们可以执行:
git mv a.txt b.txt
这样在Git中,a.txt就改名成了b.txt。如:
Git清楚知道发生了什么事情。其实上面的
git mv
就相当于执行了以下内容:
mv README README.txt
git rm README
git add README.txt
查看提交记录
查看Git提交记录的命令,我们在前面已经见过了:
git log
git log如果不带参数,它默认列出所有的提交记录,并按时间顺序从新到旧排序。
该命令的参数较多,我们可以查阅Git使用手册以了解相关细节。
为了查看特定提交的详细信息,我们可以使用
git show
带一个提交码(commit之后的字符串),如:
如果执行git show命令的时候,没有带指定提交码,它将只显示最近一次提交的详细信息。
撤销操作
有时,我们提交完了发现漏掉了文件,或者想修改提交信息;这是可以使用
git commit --amend
带--amend参数的命令尝试重新提交,如:
第一次提交时,我们漏掉了文件b;在第一次提交结束后,我们再使用带参数的commit命令尝试重新提交。最后结果是,第二次提交会直接代替第一次的提交结果。
或者有时候,我们使用了git add命令将一个文件存入暂存区,现在我们需要取消,该如何做呢:
"Changes to be commited"下面已经有提示了,使用:
git reset HEAD <file>...
如:
这样只会修改暂存区文件的内容;但如果我们添加--hard参数,
git reset HEAD --hard
再看:
本地文件e被删除了,所以要谨慎使用--hard选项;它也许会导致你当前工作目录的所有进度丢失。
如果我们想将一个修改的文件还原成上次提交时的状态,该如何做呢:
它已经给了提示:
git checkout -- <file>
git checkout命令也是危险的,它会拷贝一个文件直接覆盖当前修改的文件,改动会全部丢失;除非你确实不需要当前文件中的改动,否则尽量别使用这个命令。因为Git中,没有提交的改动文件基本再也无法恢复了。