当前位置 : 首页 » 文章分类 :  开发  »  Git-操作

Git-操作

[TOC]


Git基本操作

git config Git配置

git config -l:列出所有Git配置

Git配置文件

Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:

  • /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果使用带有--system选项的git config时,它会从此文件读写配置变量。
  • ~/.gitconfig~/.config/git/config文件:只针对当前用户。 可以传递--global 选项让 Git 读写此文件。
  • 当前使用仓库的Git目录中的config文件(就是.git/config):针对该仓库。

每一个级别覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。
在 Windows 系统中,Git 会查找$HOME目录下(一般情况下是 C:\Users\$USER)的 .gitconfig文件。 Git 同样也会寻找 /etc/gitconfig 文件,但只限于 MSys 的根目录下,即安装 Git 时所选的目标位置。

用户信息配置

当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址。 这样做很重要,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

再次强调,如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置。
很多 GUI 工具都会在第一次运行时帮助你配置这些信息。

credential.helper store存储密码

在git根目录执行git config --global credential.helper store命令,执行之后会在~/.gitconfig文件中多加如下配置项:

[credential]
    helper = store

之后在git目录执行git pull命令,会提示输入账号密码。输完这一次以后就不再需要,并且会在根目录生成一个.git-credentials文件,之后pull/push代码都不再需要输入账号密码了


git status 检查文件状态

git status命令可显示当前目录中的文件处于什么状态,是否有新添加(未被跟踪的)的文件,如果刚clone下项目就执行git status,结果为:

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

说明当前目录没有任何增删改。
向目录中添加一个文件commit.test,再次执行git status,结果为:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        commit.test

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

显示有一个未跟踪的文件。

git status -s 状态简览

使用git status -sgit status --short可更清晰简单的查看文件状态:

$ git status -s
M README
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt
  • ??:新添加的未跟踪文件
  • A:新添加到暂存区中的文件
  • 右M:修改过的文件,但是还没放入暂存区
  • 左M:该文件被修改了并放入了暂存区

例如,上面的状态报告显示: README 文件在工作区被修改了但是还没有将修改后的文件放入暂存区,lib/simplegit.rb 文件被修改了并将修改后的文件放入了暂存区。 而 Rakefile 在工作区被修改并提交到暂存区后又在工作区中被修改了,所以在暂存区和工作区都有该文件被修改了的记录。


.gitignore 配置忽略文件

如果不想某些文件纳入git版本管理,可以在项目文件夹下创建一个名为 .gitignore 的文件,列出要忽略的文件模式。例如:

$ cat .gitignore
*.[oa]
*~

第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件。一般这类对象文件和存档文件都是编译过程中出现的。 第二行告诉 Git 忽略所有以波浪符(~)结尾的文件,许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本。 此外,你可能还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。

.gitignore文件格式

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

  • 所有空行或者以 # 开头的行都会被 Git 忽略。
  • 可以使用标准的 glob 模式匹配。
  • 匹配模式可以以(/)开头防止递归。
  • 匹配模式可以以(/)结尾指定目录。
  • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。

glob模式匹配

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 使用两个星号(*) 表示匹配任意中间目录,比如a/**/z 可以匹配 a/z, a/b/z 或 a/b/c/z等。
一个较复杂的例子:

# 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

git add 跟踪新文件/暂存已修改文件

git add 命令将内容从工作目录添加到暂存区(或称为索引(index)区),以备下次提交。 当 git commit 命令执行时,默认情况下它只会检查暂存区域,因此 git add 是用来确定下一次提交时快照的样子的。

git add .,暂存当前目录下所有文件

跟踪新添加的文件commit.test
$ git add commit.test
暂存已修改的文件README.md
$ git add README.md


git commit 提交更新

git commit是提交到本地的git版本库,要想上传到GitHub远程仓库,还需要git push命令

每次准备提交前,先用git status看下,是不是都已暂存起来了,然后执行git commit命令,这种方式会启动文本编辑器(例如vim)以便输入本次提交的说明,编辑器会显示最后一次运行git status的输出,开头还有一空行,供你输入提交说明。
此外,也可以使用git commit -m命令,将提交信息与命令放在同一行:
git commit -m "Git Bash commit test"

git commit -a 暂存并提交已跟踪文件

  • 如果有文件没有被跟踪,此命令无法提交这些文件

git log 查看提交历史

默认不用任何参数的话,git log会按提交时间列出所有的更新,最近的更新排在最上面。 这个命令会列出每个提交的 SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明。

  • -n:只显示最近n条提交记录,如-2表示只显示最近2条记录
  • --pretty:指定使用不同于默认格式的方式展示提交历史
    • --pretty=oneline:将每个提交放在一行显示,查看的提交数很大时非常有用
    • --pretty=format:"%h - %an, %ar : %s":定制要显示的记录格式

git checkout – file撤销修改

git checkout -- file 可以丢弃工作区的修改
例如git checkout -- readme.txt
命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:

  • 一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
  • 一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commitgit add时的状态。
注意:git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令

git checkout -- . 或写作 git checkout .,非常危险的一条命令,会取消所有本地的修改(相对于暂存区)。相当于用暂存区的所有文件直接覆盖本地文件。


Git分支

分支简介

Git 的分支,其实本质上仅仅是指向提交对象的可变指针。 Git 的默认分支名字是 master。 在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。 它会在每次的提交操作中自动向前移动。

Git 的 “master” 分支并不是一个特殊分支。 它就跟其它分支完全没有区别。 之所以几乎每一个仓库都有 master 分支,是因为 git init 命令默认创建它,并且大多数人都懒得去改动它。


git branch 列出所有分支

git branch不加任何参数,可列出当前所有分支。
列出的分支前有*号的,表示当前检出的那一个分支。

git branch -v 列出所有分支的最后一次提交

git branch [branch-name] 创建分支

在master分支执行git branch testing即可创建一个名为testing的分支
注意:git branch 命令仅仅创建一个新分支,并不会自动切换到新分支中去。

错误:fatal: Not a valid object name: ‘master’.
git branch branch-name时出现此错误,原因是git init后还没有commit过,所以还没有真正建立master分支,先在master下git add .git commit一次,再创建分支即可

git branch -d [branch-name]删除分支

git branch -d hotfix 删除hotfix分支


git checkout 切换分支

执行git checkout testing即可切换到testing分支

分支切换会改变你工作目录中的文件
在切换分支时,一定要注意你工作目录里的文件会被改变。 如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。 如果 Git 不能干净利落地完成这个任务,它将禁止切换分支。

git checkout -b 新建并切换到分支

git checkout -b hotfix:新建并切换到hotfix分支,等于git branch hotfix命令加git checkout hotfix命令


git merge 合并分支

只需要检出到你想合并入的分支,然后运行 git merge 命令

假设从主干master拉出一个分支dev,开发完后想合并到主干,首先检出(切换)到master:
git checkout master
然后执行:
git merge dev

冲突处理

在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们,就会产生冲突。
使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件。
冲突示例:

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

这表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。 为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。

在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。


使用远程仓库

git clone 克隆远程仓库

命令格式:
git clone <远程仓库地址> <本地目录名>

git clone 实际上是一个封装了其他几个命令的命令。 它创建了一个新目录,切换到新的目录,然后 git init 来初始化一个空的 Git 仓库, 然后为你指定的 URL 添加一个(默认名称为 origin 的)远程仓库(git remote add),再针对远程仓库执行 git fetch,最后通过 git checkout 将远程仓库的最新提交检出到本地的工作目录。

git clone支持多种协议,除了HTTP(s)以外,还支持SSH、Git、本地文件协议等。

进入要存放项目的目录,例如D:\Files\Git,Git Bash执行:
git clone https://github.com/masikkk/masikkk.github.io

$ git clone https://github.com/masikkk/masikkk.github.io.git
Cloning into 'masikkk.github.io'...
remote: Counting objects: 18, done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 18 (delta 1), reused 0 (delta 0), pack-reused 9
Unpacking objects: 100% (18/18), done.
Checking connectivity... done.

git remote 列出远程仓库

git remote 命令会列出已配置的每个远程仓库的简写
git remote -v 命令会显示远程仓库的简写与对应的URL:

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

git remote add 添加远程仓库

如果你使用git clone命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以origin为简写。
执行命令git remote add <shortname> <url>来添加远程仓库,其中shortname为自定义的远程仓库的简写(别名)

git remote show [remote-name] 查看远程仓库详情

它会列出远程仓库的 URL 与跟踪分支的信息。 这些信息非常有用,它告诉你正处于 master 分支,并且如果运行 git pull,就会抓取所有的远程引用,然后将远程 master 分支合并到本地 master 分支。 它也会列出拉取到的所有远程引用。
例如:

$ git remote show origin
* remote origin
  Fetch URL: https://github.com/masikkk/masikkk.github.io.git
  Push  URL: https://github.com/masikkk/masikkk.github.io.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':

git push 推送到远程仓库

命令格式:
git push <远程主机名> <本地分支名>:<远程分支名>

注意,分支推送顺序的写法是<来源地>:<目的地>,所以git pull<远程分支>:<本地分支>,而git push<本地分支>:<远程分支>

如果省略远程分支名,则表示将本地分支推送到与之存在“追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。
git push origin master
上面命令表示,将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建。

如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略:
git push origin
上面命令表示,将当前分支推送到origin主机的对应分支。

如果当前分支与多个主机存在追踪关系,则可以使用-u选项指定一个默认主机,这样后面就可以不加任何参数使用git push
git push -u origin master
上面命令将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了

还有一种情况,就是不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机,这时需要使用–all选项。
git push --all origin
上面命令表示,将所有本地分支都推送到origin主机。

如果远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地做git pull合并差异,然后再推送到远程主机。这时,如果你一定要推送,可以使用–force选项。
git push --force origin
上面命令使用–force选项,结果导致在远程主机产生一个”非直进式”的合并(non-fast-forward merge)。除非你很确定要这样做,否则应该尽量避免使用–force选项。

push到GitHub

执行git push origin master命令后会提示输入username,但这里要输入邮箱,否则push不成功,如下:
Username for 'https://github.com': masi.1989@163.com
输入邮箱后弹出输入密码的对话框,输入GitHub登录密码,然后push成功。

$ git push origin master
Username for 'https://github.com': masi.1989@163.com
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (9/9), 898 bytes | 0 bytes/s, done.
Total 9 (delta 2), reused 0 (delta 0)
To https://github.com/masikkk/masikkk.github.io.git
   4e5e46e..e81605d  master -> master

在GitHub上新建分支

  1. git clone克隆远程仓库到本地
  2. git branch newbranch新建分支
  3. git push origin newbranch提交新分支到远程仓库

git pull 取回远程分支并与本地合并

命令格式:
git pull <远程主机名> <远程分支名>:<本地分支名>

例如,取回origin主机的next分支,与本地的master分支合并:
git pull origin next:master

如果远程分支是与当前分支合并,则冒号后面的部分可以省略:
git pull origin master
表示取回origin/master分支,再与当前分支合并。实质上,git pull等同于先做git fetch,再做git merge
git fetch origin
git merge origin/master

追踪关系(跟踪分支)

在某些场合,Git会自动在本地分支与远程分支之间,建立一种追踪关系(tracking)。比如,在git clone的时候,所有本地分支默认与远程主机的同名分支,建立追踪关系,也就是说,本地的master分支自动”追踪”origin/master分支。或者可以这么说,当克隆一个仓库时,它通常会自动地创建一个跟踪 origin/master 的 master 分支。

Git也允许手动建立追踪关系:
git branch --set-upstream master origin/master
上面命令指定本地master分支追踪origin/master分支。

如果当前分支与远程分支存在追踪关系,git pull就可以省略远程分支名:
git pull origin
上面命令表示,本地的当前分支自动与对应的origin主机”追踪分支”(remote-tracking branch)进行合并。

如果当前分支只有一个追踪分支,连远程主机名都可以省略:
git pull
上面命令表示,当前分支自动与唯一一个追踪分支进行合并。


移除远程仓库

如果不想Git与现在的远程仓库关联了,可以执行:
git remote rm origin
即删除clone时默认添加的远程仓库origin


删除远程分支

运行带有--delete选项的git push命令来删除一个远程分支。
例如:如果想要从服务器上删除serverfix分支,运行下面的命令:
git push origin --delete serverfix

或者在git push命令中省略本地分支名,则表示删除指定的远程分支,因为这等同于推送一个空的本地分支到远程分支。
$ git push origin :master
等同于
$ git push origin --delete master
上面命令表示删除origin主机的master分支。

注意:如果此远程分支为项目的默认分支,无法删除,会提示:
! [remote rejected] hexo_branch (refusing to delete the current branch: refs/heads/hexo_branch)
需要登录GitHub(或其他Git托管网站),将项目的默认分支修改为其他分支。


参考


Git子模块

git clone –recursive 克隆带有子模块的远程仓库

如果某个项目需要包含并使用另一个项目,例如第三方库,需要使用git clone --recursive命令进行递归clone。
如果只是在主项目中git clone,虽然会生成子模块的目录,但其中还没有任何文件,需要再次执行git submodule initgit submodule update命令来初始化和拉取子模块数据。而git clone --recursive命令则可以一次性自动初始化并更新仓库中的每一个子模块。
例如:
$ git clone --recursive https://github.com/chaconinc/MainProject

错误:git clone --recursive时提示fatal: reference isn’t a tree

fatal: reference isn’t a tree: 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
Unable to checkout '6c5e70b984a60b3cecd395edd5ba7575bf58e0' in submodule path 'cpy-leveldb'

原因是我们本地对子模块进行了修改但是并没有推送到子模块的远程仓库,然后在主项目中提交了一个指向那个非公开状态的指针然后推送远程仓库。当在其他地方进行git submodule update或迭代clone时,那个子模块系统会找不到所引用的提交。


git submodule add 添加子模块

将一个已存在的 Git 仓库clone下来并添加为正在工作的仓库的子模块。 你可以通过在git submodule add命令后面加上想要跟踪的项目 URL 来添加新的子模块。

$ git submodule add https://github.com/wzpan/hexo-theme-freemind.git themes/freemind
Cloning into 'themes/freemind'...
remote: Counting objects: 2136, done.
remote: Total 2136 (delta 0), reused 0 (delta 0), pack-reused 2136
Receiving objects: 100% (2136/2136), 35.03 MiB | 869.00 KiB/s, done.
Resolving deltas: 100% (986/986), done.
Checking connectivity... done.

通过ls -a命令可以看到主项目下多了一个.gitmodules隐藏文件,内容为:

[submodule "themes/freemind"]
        path = themes/freemind
        url = https://github.com/wzpan/hexo-theme-freemind.git

如果有多个子模块,该文件中就会有多条记录。


git submodule update –remote 更新子模块

如果项目中的子项目(例如第三方库)的远程仓库有了更新,我们可以进入某个子项目目录,执行git pull来更新该子项目,或者直接在主项目目录中执行git submodule update --remote [submodule-name]来更新指定子项目,如果直接输入git submodule update --remote,会尝试更新所有子项目。


提交带有子模块的项目

与普通提交无异,还是在主目录中通过git add .git commit -m提交,如果要提交到自己主项目的远程仓库,还是git push命令。如果使用GitHub的话,提交后上GitHub页面查看,会发现子项目是直接链接到第三方库的GitHub页面的。

但是如果子模块不是自己的项目,是无法push到原作者的远程仓库的,这点一定要注意。


删除子模块

  • 删除submodule目录的.git隐藏文件夹。
  • 修改.gitmodules文件,去掉submodule子模块,如果只有这一个子模块的话,直接删除.gitmodules文件
  • 修改.git\config文件,去掉submodule子模块;
  • 删除.git\modules\submodule目录;
  • git rm --cached submodule,使submodule目录脱离Git版本控制

如果不需要submodule子模块了,直接删除物理文件夹;如果是想把submodule当做普通文件夹继续进行Git版本管理,再执行git add .将其纳入Git版本控制。


参考


上一篇 Hexo博客(05)Hexo定制与插件

下一篇 Hexo博客(04)free2mind主题配置

阅读
5,840
阅读预计23分钟
创建日期 2016-04-03
修改日期 2018-01-08
类别
标签
百度推荐