progit之 git 基础(2)(获取Git仓库、记录更新到仓库、撤销操作、远程仓库的使用)

git 基础

本章涵盖了在使用Git完成各种工作中将要使用的各种基本命令。在学习完本章后,你应该能配置并初始化一个仓库(repository)、开始或停止跟踪(track)文件、暂存(stage)或提交更改(commit)。同时本章也演示如何配置Git来忽略指定的文件和文件模式、如何迅速而简单地撤销错误操作、如何浏览你的项目的历史版本以及不同提交间的差异、如何向你的远程仓库推送以及如何从你的远程仓库拉取文件

一、获取git仓库

1. 在现有目录中初始化仓库

如果打算将一个本地文件夹使用git来进行管理,只需在该文件夹目录下执行

git init

该命令将会创建一个名为 .git 的子目录,这个子目录含有你初始化的Git仓库中所有的必须文件,这些文件是Git仓库的骨干。但是这一步,我们只是做了一个初始化的操作,项目里的文件并没有被跟踪。

如果当前这个文件夹里有其他文件的话,通过下列命令来跟踪这些文件并提交

git add *.c
git add LICENSE
git commit -m 'initial project version'

现在,你已经得到了一个实际维护(或跟踪)着若干个文件的Git仓库

2. 克隆现有的仓库

如果你想获得一份已经存在了的Git仓库的拷贝,需要使用 git clone 命令。Git 克隆的是该Git仓库服务器上的几乎所有数据,而不是仅仅复制完成你的工作所需要文件,这是Git区别于其他版本控制系统的一个重要特性。

克隆仓库的命令格式是git clone [url]。比如,要克隆Git的可链接库 libgit2,可使用如下命令:

git clone https://github.com/libgit2/libgit2.git

这会在当前目录下创建一个名为 “libgit2” 的目录,并在这个目录下初始化一个 .git 文件夹,从远程仓库拉取下所有数据放入 .git 文件夹,然后从中读取最新版本的文件的拷贝。如果你想克隆远程仓库的时候,自定义本地仓库的名字,可以使用如下命令,在本地创建的仓库名字将变为 mylibgit

git clone https://github.com/libgit2/libgit2.git mylibgit

git 支持多种传输协议,上面使用的是 https, 也可以使用git协议或者ssh传输协议,比如 user@server:path/to/repo.git

二、记录每次更新到仓库

工作目录下的每一个文件不外乎两种状态:已跟踪或未跟踪。已跟踪是指那些被纳入了版本控制的文件,再上一次快照中有他们的记录,工作一段时间后,他们的状态可能处于未修改,已修改或者已放入暂存区。工作目录中除已跟踪文件以外的其他文件都属于未跟踪文件,他们既不存在于上次快照的记录中,也没有放入暂存区。

编辑过某些文件之后,由于自上次提交后你对他们做了修改,Git将他们标记为已修改文件。我们将这些修改过的文件放入暂存区,然后提交所有暂存了的修改,如此反复。

1. 检查当前文件状态:

要查看哪些文件处于什么状态,可以使用 git status 命令。

# 这说明你现在的工作目录相当干净。换句话说,所有已跟踪文件在上次提交后都未被更改过。 此外,上面的信息还表明,当前目录下没有出现任何处于未跟踪状态的新文件,否则 Git 会在这里列出来。 最后,该命令还显示 了当前所在分支,并告诉你这个分支同远程服务器上对应的分支没有偏离。
$ git status
  On branch master
  nothing to commit, working directory clean


# 现在可以看到有一个新建的README文件出现在Untracked files下面。未跟踪的文件意味着Git在之前 的快照(提交)中没有这些文件;Git 不会自动将之纳入跟踪范围,除非你明明白白地告诉它“我需要跟踪该文 件”。
$ git status
  On branch master
  Untracked files:
    (use "git add <file>..." to include in what will be committed)

      README

  nothing added to commit but untracked files present (use "git add" to track)

git status 命令的输出十分详细,如果使用 git status -s 或者 git status --short,将得到一种更为紧凑的格式输出。

# 新添加的未跟踪文件前面有 ?? 标记
# 新添加到暂存区中的文件前面有 A 标记
# 修改过的文件前面有 M 标记。出现在右边的 M 表示该文件被修改了但是还没放入暂存区;出现在靠左 边的 M 表示该文件被修改了并放入了暂存区。两个M表示在工作区被修改并提交到暂存区后又在工作区中被修改了。
$ git status -s
    M README
  MM Rakefile
  A  lib/git.rb
  M  lib/simplegit.rb
  ?? LICENSE.txt

2. 跟踪新文件、暂存已修改文件

使用命令 git add 开始跟踪一个文件,或者暂存已修改文件

$ git add README

此时再查看文件状态,会发现README文件已经被跟踪,并处于暂存状态

$ git status
On branch master
Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)

      new file:   README

3. 忽略文件

有些文件无需纳入Git的管理,也不希望他们总出现在未跟踪文件列表。这种情况下,我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。

# 第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件。一般这类对象文件和存档文件都是编译过程中出现的。
# 第二 行告诉 Git 忽略所有以波浪符(~)结尾的文件
# 此外,你可能还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。
$ cat .gitignore
  *.[oa]
  *~

要养成一开始就设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件

文件 .gitignore 的格式规范如下:

• 所有空行或者以 # 开头的行都会被 Git 忽略。

• 可以使用标准的 glob 模式匹配。

• 匹配模式可以以(/)开头防止递归。

• 匹配模式可以以(/)结尾指定目录。

• 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。

# no .a files
*.a

# but do track lib.a, even though you're ignoring .a files above
!lib.a

# only ignore the TODO file in the current directory, not subdir/TODO
/TODO

# ignore all files in the build/ directory
build/

# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt

# ignore all .pdf files in the doc/ directory
doc/**/*.pdf
 

4. 查看已暂存和未暂存的修改

git diff 将通过文件补丁的格式显示具体哪些行发生了改变

要查看尚未暂存的文件更新了哪些部分,不加参数直接输入 git diff

若要查看已暂存的将要添加到下次提交里的内容,可以用 git diff --cached 命令 或者 git diff --staged 

5. 提交更新

每次提交前,先用git status看下,是不是都已暂存起来了,然后再运行提交命令 git commit,这种方式会启动文本编辑器以便输入本次提交的说明。

另外,也可以在commit命令后添加 -m 选项,将提交信息与命令放在同一行。

$ git commit -m "Story 182: Fix benchmarks for speed"

 6. 跳过使用暂存区域

Git提供了一个跳过使用暂存区域的方式,只要在提交的时候,给 git commit 加上 -a选项,Git就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过git add步骤。

  7. 移除文件

要从Git中移除某个文件,就必须要从已跟踪文件清单中移除(确切的说,是从暂存区域移除),然后提交。

可以使用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。

如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changes not stated for commit” 部分。

$ rm PROJECTS.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
    (use "git add/rm <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working
  directory)

          deleted:    PROJECTS.md

no changes added to commit (use "git add" and/or "git commit -a")

然后再运行 git rm 记录此次移除文件的操作,下一次提交时,该文件就不再纳入版本管理了。

$ git rm PROJECTS.md
rm 'PROJECTS.md'
$ git status
On branch master
  Changes to be committed:
    (use "git reset HEAD <file>..." to unstage)

      deleted:    PROJECTS.md

 如果删除之前已经修改过并且已经放到暂存区域的文件,则必须要用强制删除选项 -f 。 这是一种安全特性,用于防止误删还没有添加到快照的数据,这样的数据不能被Git恢复。

另外一种情况:我们想让文件保留在本地,但是并不想让Git继续跟踪。当你忘记添加 .gitignore文件,不小心把日志文件或者编译生成文件添加到暂存区时,这一做法尤其有用,为达这一目的,使用 --cached 选项。 git rm 命令后面可以列出文件或者目录的名字。

git rm --cached README
# 此命令删除log/目录下扩展名为.log的所有文件
git rm log/\*.log

 8. 移动文件

要在Git中对文件改名,可以这么做:

$ git mv file_from file_to

它相当于以下三条命令:

$ mv file_from file_to

$ git rm file_from

$ git add file_to

9. 查看提交历史

$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

      changed the version number

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

      removed unnecessary test

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

      first commit

git log 不带任何参数的话,会按提交时间列出所有更新,最近的更新排在上面。

选项:

-p: 用来显示每次提交的内容差异, 也可以加上 -2 来仅显示最近两次提交。

--stat:显示每次提交的简略统计信息

--pretty:指定使用不同于默认格式的方式展示提交历史。这个选项有一些内建的子选项供你使用。比如用 oneline 将每个提交放在一行显示,查看的提交书很大时非常有用。另外,还有short、full 和 fuller 可以用。format 可以定制要显示的记录格式

--graph:当 online 或者 format 与 --graph 结合使用时尤其有用。这个选项形象地展示了你的分支、合并历史

-S:可以列出那些添加或移除了某些字符串的提交。

-- {path}: 如果只关心某些文件或者目录的提交历史,可以在gitlog选项的最后指定他们的路径。因为是放在最后位置的选项, 所以我们用两个短划线(--)隔开之前的选项和后面限定的路径名

$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 changed the version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test
a11bef06a3f659402fe7563abf99ad00de2209e6 first commit

  $ git log --pretty=format:"%h - %an, %ar : %s"
  ca82a6d - Scott Chacon, 6 years ago : changed the version number
  085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
  a11bef0 - Scott Chacon, 6 years ago : first commit

  $ git log --pretty=format:"%h %s" --graph
  * 2d3acf9 ignore errors from SIGCHLD on trap
  *  5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
  |\
  | * 420eac9 Added a method for getting the current branch.
  * | 30e367c timeout code and tests
  * | 5a09431 add timeout protection to grit
  * | e1193f8 support for heads with slashes in them
  |/
  * d6016bc require time for xmlschema
  *  11d191e Merge branch 'defunkt' into local

# 找出添加或移除了某一个特定函数的饮用的提交
$ git log -Sfunction_name

 三、撤销操作

在任何一个阶段,你都有可能想撤销某些操作。但是有些撤销操作是不可逆的,这是在使用Git过程中,会因为操作失误而导致之前工作丢失的少有的几个地方之一。

有时我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。此时可以运行带有 --amend 选项的提交命令尝试重新提交。这个命令会将暂存取中的文件提交,如果自上次提交以来你还未做任何修改(例如,在上次提交之后马上执行了此命令),那么快照会保持不变,而你所修改的只是提交信息。

# 下面的操作最终只会有一个提交,第二次提交将会代替第一次提交的结果
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend

1. 取消暂存的文件

如果你修改了两个文件并且想要将它们作为两次独立的修改提交,但却意外的输入了 git add * 暂存了他们两个,如何取消一个暂存呢?

git status 命令提示你,在 “changes to be committed” 文字下方,提示使用 git reset HEAD <file> ...来取消暂存。

如: $ git reset HEAD CONTRIBUTING.md

虽然在使用时加上 --hard 选项可以令 git reset 成为一个危险的命令,可能导致工作目录中当前进度丢失,但是不加选项地使用 git reset 并不危险——他指挥修改暂存区域。 

2. 撤销对文件的修改

如果你并不想保留对某个文件所做的修改,该如何方便的撤销修改——将它还原成上次提交时的样子?

git status 也提示了应该如何做, 在“Changes not stages for commit”下方,提示 use "git chechout -- <file> ..." to discard changes in working directory

如:$ git checkout -- CONTRIBUTING.md

git checkout -- <file> 是一个危险的命令,你对那个文件做的任何修改都会消失—你只是拷贝了另一个文件来覆盖它。

除非你确实清楚不想要那个文件了,否则不要使用这个命令。

四、远程仓库的使用

为了能在任意 Git 项目上协作,你需要知道如何管理自己的远程仓库。远程仓库是指托管在因特网或其他网络中的你的项目的版本库。

你可以有好几个远程仓库,有些仓库对你只读,有些可以读写。与他人协作涉及管理远程仓库以及根据需要推送或拉取数据。管理远程仓库包括了解如何添加远程仓库、移除无效的远程仓库、管理不同的远程分支并定义它们是否被跟踪的等等。

1. 查看远程仓库

如果想查看你已经配置的远程仓库服务器,可以运行git remote 命令,它会列出你指定的每一个远程服务器的简写。

你也可以指定选项 -v ,会显示需要读写远程仓库使用的Git保存的简写与其对应的URL

如果想查看某一个远程仓库的更多信息,可以使用 git remote show [remote-name] 命令

 $ git remote
 origin

  $ git remote -v
  origin  https://github.com/schacon/ticgit (fetch)
  origin  https://github.com/schacon/ticgit (push)

  $ git remote show origin
  * remote origin
    Fetch URL: https://github.com/schacon/ticgit
    Push  URL: https://github.com/schacon/ticgit
    HEAD branch: master
    Remote branches:
      master                               tracked
      dev-branch                           tracked
    Local branch configured for 'git pull':
      master merges with remote master
    Local ref configured for 'git push':
      master pushes to master (up to date)

2. 添加远程仓库

运行 git remote add <shortname> <url> 添加一个新的远程 Git 仓库,同时指定一个你可以轻松引用的简写

  $ git remote
  origin
  $ git remote add pb https://github.com/paulboone/ticgit
  $ git remote -v
  origin  https://github.com/schacon/ticgit (fetch)
  origin  https://github.com/schacon/ticgit (push)
  pb  https://github.com/paulboone/ticgit (fetch)
  pb  https://github.com/paulboone/ticgit (push)

# 现在你可以在命令行中使用 pb 来代替整个 url

3. 从远程仓库抓取与拉取

从远程仓库获取数据,可以执行:

$ git fetch [remote-name]

如果你使用clone命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以“origin”为简写。

git fetch命令会将数据拉取到你的本地仓库,它并不会自动合并或修改你当前的工作。当准备好时你必须手动将其合并入你的工作。

4. 推送到远程仓库

当你想分享你的项目时,必须将其推送到上游。只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。

如果有其他人先推送到上游,你再推送,你的推送就会被拒绝。你必须先将它们的工作拉取下来并将其合并进你的工作后才能推送。

git push [remote-name] [branch-name]

$ git push origin master

5. 远程仓库的移除与重命名

如果想重命名引用的名字可以运行 git remote rename 去修改一个远程仓库的简写名。

这样同样也会修改你的远程分支名字,那些过去引用pb/master 的现在会引用 paul/master

如果因为某些原因想要移除一个远程仓库,可以使用 git remote rm

$ git remote rename pb paul
$ git remote
origin
paul

  $ git remote rm paul
  $ git remote
  origin

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2020-01-05 22:31  mlllily  阅读(294)  评论(0编辑  收藏  举报