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

Git-操作

git基本操作笔记


git config

Git配置

git config -l 列出所有git配置

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

git配置文件.gitconfig

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 时所选的目标位置。


user.name/user.email 用户信息配置

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

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

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

不同项目配置不同用户信息

比如自己公司内部的项目提交时设置的用户名为自己的真实姓名,但是在github上提交时,可能不想暴露真实姓名,这时候就不能采用通用的配置了,就要单独设置每个项目的git配置。
由于每个git项目下都会有一个隐藏的.git文件夹 ,将终端的工作目录设置到,相应的项目根目录下,执行ls -all
命令,显示所有文件,即可看到.git的隐藏文件夹。通过cd .git 进入该目录,发现该目录下有个config文件,采用
open config 命令打开,添加如下配置:
[user]
name = XXX(自己的名称英文)
email = XXXX(邮箱)
保存,command+s 即可。这时候就为该项目配置了独立的用户名和邮箱,这时提交代码时,提交日志上显示的就是设置的名称,当然github这种会根据设置的邮箱来设置对应的用户名。
当然也可以通过命令行的方式(即要去掉–global参数)去设置单独的git配置,只需要在 .git 文件夹下。 例如执行如下命令:
git config user.name “xxxxx”
git config user.email “xxx@xx”
来修改当前项目提交代码时用到的用户名和邮箱。

如果全局的配置和当前项目的单独配置中出现相同的配置选项,比如全局和项目都设置了user.name ,那么在该项目中进行git操作时,会默认采用该项目配置的用户名。


core.autocrlf 换行符自动转换

1、本人在Windows系统上工作,同伴用其他系统时
假如你正在 Windows 上写程序,而你的同伴用的是其他系统(或相反),你可能会遇到 CRLF 问题。 这是因为 Windows 使用回车(carriage return, CR)和换行(line feed, LF)两个字符来结束一行,而 Mac 和 Linux 只使用换行(line feed, LF)一个字符。 虽然这是小问题,但它会极大地扰乱跨平台协作。许多 Windows 上的编辑器会悄悄把行尾的换行字符转换成回车和换行,或在用户按下 Enter 键时,插入回车和换行两个字符。

Git 可以在你提交时自动地把回车和换行(CRLF)转换成换行(LF),而在检出代码时把换行(LF)转换成回车和换行(CRLF)。 你可以用 core.autocrlf 来打开此项功能。 如果是在 Windows 系统上,把它设置成 true,这样在检出代码时,换行会被转换成回车和换行:

# 提交时转换为LF,检出时转换为CRLF
git config --global core.autocrlf true

2、本人在Linux或Mac上工作时
如果使用以换行作为行结束符的 Linux 或 Mac,你不需要 Git 在检出文件时进行自动的转换;然而当一个以回车加换行作为行结束符的文件不小心被引入时,你肯定想让 Git 修正。 你可以把 core.autocrlf 设置成 input 来告诉 Git 在提交时把回车和换行转换成换行,检出时不转换:

# 提交时转换为LF,检出时不转换
git config --global core.autocrlf input

这样在 Windows 上的检出文件中会保留回车和换行,而在 Mac 和 Linux 上,以及版本库中会保留换行。

3、所有人都仅在Windows上工作时
如果你是 Windows 程序员,且正在开发仅运行在 Windows 上的项目,可以设置 false 取消此功能,把回车保留在版本库中:

# 提交检出均不转换
git config --global core.autocrlf false

8.1 自定义 Git - 配置 Git
https://git-scm.com/book/zh/v2/自定义-Git-配置-Git


core.safecrlf 换行符检查

#拒绝提交包含混合换行符的文件
git config --global core.safecrlf true

#允许提交包含混合换行符的文件
git config --global core.safecrlf false

#提交包含混合换行符的文件时给出警告
git config --global core.safecrlf warn

core.quotepath 中文文件名乱码

在默认设置下,中文文件名在工作区状态输出,查看历史更改概要,以及在补丁文件中,文件名的中文不能正确地显示,而是显示为\xxx\xxx 这种八进制的字符编码,比如:

git status
    modified:   "source/_posts/\345\267\245\345\205\267/Git-\346\223\215\344\275\234.md"

这是因为git对0x80以上的字符进行了quote
通过将Git配置变量 core.quotepath 设置为false,就可以解决中文文件名称在这些Git命令输出中的显示问题

#不对0x80以上的字符进行quote,解决git status/commit时中文文件名乱码
git config --global core.quotepath false

MAC上git diff/git log中文文件名乱码

配置了git config –global core.quotepath false后,git status中文文件名不乱码了,但git diff和git log中文文件名还是乱码,查了下
解决方案:
echo $LANG;
输出结果为空
执行export LANG=”zh_CN.UTF-8”命令,问题解决。
或者写到profile文件中,编辑~/.bash_profile,写入:
export LANG=”zh_CN.UTF-8” 保存后执行 source ~/.bash_profile使配置文件生效


credential.helper store存储密码

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

[credential]
    helper = store

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


core.ignorecase文件名大小写敏感配置

git默认是文件名大小写不敏感的,即Java.txt 和java.txt会被当做是同一个文件,同样,如果只将Java.txt的文件名修改为java.txt,文件内容不动,git status是检测不出改动的。

如何修改文件名大小写?

1、设置git库为大小写敏感(不建议)
git config core.ignorecase false
用这种方法进行重命名,用git status就可以识别出修改了,但是不推荐用这种方式,因为在更新这种修改的时候会有麻烦。

2、使用git mv命令改文件名
使用git mv命令修改文件名(仅当core.ignorecase为true时可用)

$ git mv ABC.java Abc.java
$ git status
......
            renamed: ABC.java -> Abc.java

此时的状态是renamed,git commit即可。

如果使用Eclipse中的git插件进行仅涉及大小写的重命名,无论core.ignorecase设置为true还是false或者没有设置该项,修改之后均可正常提交,能识别出文件大小写重命名。


git status

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 files跟踪新文件/暂存已修改文件

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

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

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


git rm

git rm 语法
git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>…

git rm file git仓库和本地同时删除

git rm file,从git仓库中删除文件,同时在本地工作目录删除文件

git rm -r 删除目录

git rm –r *,可以递归删除,即如果后面跟的是一个目录做为参数,则会递归删除整个目录中的所有子目录和文件:

git rm -f file 删除暂存区的文件加-f

git rm -f <file>,如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f

git rm –cached file git仓库删除但本地保留

git rm --cached file,把文件从暂存区域移除,但仍然希望保留在当前工作目录中,换句话说,仅是从跟踪清单中删除,使用 –cached 选项即可

Git 基本操作
http://www.runoob.com/git/git-basic-operations.html

删除git仓库中文件但本地保留

对于eclipse的maven项目,.classpath.project.settings/target/ 等文件和目录如果被提交到git仓库,并不方便其他项目成员使用,而且因为本地的环境变化,还会频繁要求提交这些文件的修改,所以这些文件不建议纳入git版本控制,通常.gitignore文件配置如下:

/target/
/.settings/
/.project
/.classpath

不过如果这些文件之前已经提交过,即已经被纳入git版本控制中,配置.gitignore也并不会将其从git版本控制中移除,这时需要在命令行中使用git rm --cached命令。Eclipse中EGit图形界面上没找到怎么操作。

我们想把文件从Git仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让Git继续跟踪。当你忘记添加.gitignore文件,不小心把一个很大的日志文件或一堆.a这样的编译生成文件添加到暂存区时,这一做法尤其有用。为达到这一目的,需要使用git rm命令的--cached选项。
打开Git Bash命令行,执行如下命令将这些文件从git仓库删除:

git rm -r --cached .settings/
git rm --cached .classpath
git rm --cached .project
git commit -m "remote .settings .classpath from git"

类似rm命令,删除文件夹时要带-r选项,最后别忘了还要git commit提交才能生效。


git clean

git clean -f 删除 untracked files

git clean -f

git clean -fd 连 untracked 的目录也一起删掉

git clean -fd

git clean -xfd 连 gitignore 的untrack 文件/目录也一起删掉

git clean -xfd
慎用,一般这个是用来删掉编译出来的 .o之类的文件用的

git clean -nf 显示clean命令要删除的文件

在用上述 git clean 前,墙裂建议加上 -n 参数来先看看会删掉哪些文件,防止重要文件被误删。加-n参数的clean命令不会真正删除。
git clean -nxfd
git clean -nf
git clean -nfd


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 commit –amend 改写提交

改变最近一次提交也许是最常见的重写历史的行为。对于你的最近一次提交,你经常想做两件基本事情:改变提交说明,或者改变你刚刚通过增加,改变,删除而记录的快照。

如果你只想修改最近一次提交说明,这非常简单:git commit –amend
这会把你带入文本编辑器,里面包含了你最近一次提交说明,供你修改。当你保存并退出编辑器,这个编辑器会写入一个新的提交,里面包含了那个说明,并且让它成为你的新的最近一次提交。

如果你完成提交后又想修改被提交的快照,增加或者修改其中的文件,可能因为你最初提交时,忘了添加一个新建的文件,这个过程基本上一样。你通过修改文件然后对其运行git add或对一个已被记录的文件运行git rm,随后的git commit –amend会获取你当前的暂存区并将它作为新提交对应的快照。


git rebase

git rebase合并整理commit

在使用 Git 作为版本控制的时候,我们可能会由于各种各样的原因提交了许多临时的 commit,而这些 commit 拼接起来才是完整的任务。那么我们为了避免太多的 commit 而造成版本控制的混乱,通常我们推荐将这些 commit 合并成一个。

1、查看提交历史,git log
首先你要知道自己想合并的是哪几个提交,可以使用git log命令来查看提交历史,假如最近4条历史如下:
commit 3ca6ec340edc66df13423f36f52919dfa3……
commit 1b4056686d1b494a5c86757f9eaed844……
commit 53f244ac8730d33b353bee3b24210b07……
commit 3a4226b4a0b6fa68783b07f1cee7b688…….
历史记录是按照时间排序的,时间近的排在前面。

2、git rebase
想要合并1-3条,有两个方法

1)从HEAD版本开始往过去数3个版本
git rebase -i HEAD~3

2)指名要合并的版本之前的版本号
git rebase -i 3a4226b

其中,-i 的参数是不需要合并的 commit 的 hash 值
请注意3a4226b这个版本是不参与合并的,可以把它当做一个坐标

3、选取要合并的提交
执行了rebase命令之后,会弹出一个窗口,头几行如下:
pick 3ca6ec3 ‘注释…’
pick 1b40566 ‘注释…’
pick 53f244a ‘注释…’

p, pick 使用这条 commit
r, reword 使用这条 commit 但是要修改 commit message
e, edit 使用这条 commit 但是要修改 commit messaage // 这里和 reword 使用方法一样, 但 reword 在 :wq 后会直接让你进入修改编辑, edit :wq 后要再使用 git commit –amend 进入修改
s, squash 使用这条 commit, 但是要与上一条 commit 合并, 并保留自身 commit message
f, fixup 与 squash 一样, 但是舍弃 自身 commit message
x, exec 执行命令

比如:
pick 3ca6ec3 ‘注释…’
fixup 1b40566 ‘注释…’
fixup 53f244a ‘注释…’
会将后两条commit删掉,只保留第一条

比如:
pick 3ca6ec3 ‘注释…’
squash 1b40566 ‘注释…’
squash 53f244a ‘注释…’
会将后两条commit信息合并到第一条末尾,然后将后两条commit删掉

输入wq保存并推出, 再次输入git log查看 commit 历史信息,你会发现这两个 commit 已经合并了。

如果有冲突,需要修改,修改的时候要注意,保留最新的历史,不然我们的修改就丢弃了。
修改以后要记得敲下面的命令:
git add .
git rebase –continue
如果你想放弃这次压缩的话,执行以下命令:
git rebase –abort

注意事项:如果这个过程中有操作错误,可以使用 git rebase –abort来撤销修改,回到没有开始操作合并之前的状态。

(Git)合并多个commit
https://segmentfault.com/a/1190000007748862


git log 查看提交历史

git log 倒序查看日志

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

-n:只显示最近n条提交记录,如-2表示只显示最近2条记录
--pretty:指定使用不同于默认格式的方式展示提交历史

git log –pretty=oneline 单行显示

--pretty=oneline:将每个提交放在一行显示,查看的提交数很大时非常有用
--pretty=format:"%h - %an, %ar : %s":定制要显示的记录格式


git checkout

git checkout [branch-name] 切换分支

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

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

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

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

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 checkout .,非常危险的一条命令,会取消所有本地的修改(相对于暂存区)。相当于用暂存区的所有文件直接覆盖本地文件。


git checkout otherBranch files 合并其他分支的指定文件

git merge 合并的时候会将两个分支的内容完全合并,如果想合并一部分肯定是不行的。那怎么办?

如何从其他分支merge指定文件到当前分支,git checkout 是个合适的工具。
git checkout source_branch <path>...

例如:使用git checkout 将B分支上的系统消息功能添加到A分支上

# 当前在A分支上
$ git branch
  * A
    B
# 将B分支上的下列文件合并到A分支上
$ git checkout B message.html message.css message.js other.js

注意:在使用git checkout某文件到当前分支时,会将当前分支的对应文件强行覆盖

这里新增文件没问题,但是A分支上原有的other.js会被强行覆盖,如果A分支上的other.js有修改,在checkout的时候就会将other.js内容强行覆盖

git小技巧–如何从其他分支merge个别文件或文件夹
https://segmentfault.com/a/1190000008360855


git reflog 查看commit id

git reset 版本回退

先查看更新的版本日志:
git reflog
得到commit_id
回退到某一个版本:
git reset –hard commit_id

git reset Head 撤销add(暂存)

git add 如果添加了错误的文件的话

撤销操作
git status 先看一下add 中的文件
git reset HEAD 如果后面什么都不跟的话 就是上一次add 里面的全部撤销了
git reset HEAD XXX/XXX/XXX.java 就是对某个文件进行撤销了

git reset –hard commit_id 撤销commit并修改代码

git reset --hard commit_id,完成撤销,同时将代码恢复到前一commit_id 对应的版本。

git reset commit_id 撤销commit不修改代码

git reset commit_id,完成Commit命令的撤销,但是不对代码修改进行撤销,可以直接通过git commit 重新提交对本地代码的修改。

撤销已commit但未push的修改

git log 找到上次git commit的 id,即commit后面那一长串
git reset --hard commit_id,完成撤销,同时将代码恢复到前一commit_id 对应的版本。
git reset commit_id,完成Commit命令的撤销,但是不对代码修改进行撤销,可以直接通过git commit 重新提交对本地代码的修改。

例如:
git reset a1349f9b370a9890746a8792a441995751e364c3

撤销git pull

比如一不小心拉取了错误的远程分支来和本地分支合并,可以通过下面两种方法取消:
方法一:
git log
查看git commit日志,每个commit后有一串字符串,commit xxxxxxxxx,表示此commit的id
git reset –hard xxxxxxx
xxxxxxx就是自己想回退的commit对应的id
然后git status发现git pull的内容都没有了。

方法二:
git reflog 命令查看历史变更记录,例如:

6a8f898b (HEAD -> feature-0730, origin/feature-0730) HEAD@{0}: checkout: moving from dev-0730 to feature-0730
0879c18e (dev-0730) HEAD@{1}: reset: moving to 0879c18e
72d76bc7 (origin/dev-0730) HEAD@{2}: commit: 添加xxx
0879c18e (dev-0730) HEAD@{3}: commit: 添加xxxx
7142ef99 HEAD@{4}: commit: 添加xxxxxx
d5d7eced HEAD@{5}: checkout: moving from 3.2-so-fix to dev-0730
7c485a8a (3.2-so-fix) HEAD@{6}: commit: 新增xxxxx接口
a6784867 (3.2) HEAD@{7}: checkout: moving from 3.2 to 3.2-so-fix
a6784867 (3.2) HEAD@{8}: checkout: moving from 3.2 to 3.2
a6784867 (3.2) HEAD@{9}: checkout: moving from master to 3.2
1f6ba2fa (origin/master, origin/feature-0713, origin/HEAD, origin/0711-master-config, master) HEAD@{10}: pull: Fast-forward
b41faa56 HEAD@{11}: checkout: moving from dev-0730 to master
d5d7eced HEAD@{12}: commit: 新增xxx查询
43c3b5bb HEAD@{13}: commit: 新增xxxx查询
8ad4345e HEAD@{14}: commit (amend): 增加xxxx
3d8eb583 HEAD@{15}: commit: 更新xxxx配置
94238f4c HEAD@{16}: commit: 添加xxxxx配置
60152f92 HEAD@{17}: commit: 添加xxxx类
4b4bb804 HEAD@{18}: commit: 添加xxxxx代理类
3399c7d8 (feature-0730) HEAD@{19}: checkout: moving from feature-0730 to dev-0730
3399c7d8 (feature-0730) HEAD@{20}: checkout: moving from master to feature-0730
b41faa56 HEAD@{21}: pull: Fast-forward
9f15e746 (origin/0705-dev, feature-service) HEAD@{22}: checkout: moving from dev-xxxx to master
1347d4f4 (dev-xxxxxxxxx) HEAD@{23}: commit: xxxxxxx
987f7d54 (origin/dev-xxxxxxxxx) HEAD@{24}: checkout: moving from dev-xxxxxxxxx to dev-xxxxxxxxx
987f7d54 (origin/dev-xxxxxxxxx) HEAD@{25}: checkout: moving from dev-xxxxxxxxx to dev-xxxxxxxxx
987f7d54 (origin/dev-xxxxxxxxx) HEAD@{26}: checkout: moving from feature-service to dev-xxxxxxxxx

此记录中不只有自己的commit,还有其他人在此分支上的操作。
git reset --hard xxxxx
xxxx是自己想回退的操作记录的id,即开头的一串字符串


git branch

Git 的分支,其实本质上仅仅是指向提交对象的可变指针。 Git 的默认分支名字是 master。 在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。 它会在每次的提交操作中自动向前移动。
Git 的 “master” 分支并不是一个特殊分支。 它就跟其它分支完全没有区别。 之所以几乎每一个仓库都有 master 分支,是因为 git init 命令默认创建它,并且大多数人都懒得去改动它。

git branch 列出所有本地分支

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

git branch -r 列出所有远程分支

git branch -r 列出所有远程分支

git branch -a 列出所有远程和本地分支

git branch -a 列出所有分支,包括远程分支和本地分支

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

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

git 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 –set-upstream-to 设置分支追踪关系

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

Git也允许手动建立追踪关系:
git branch --set-upstream master origin/master
上面命令指定本地master分支追踪origin/master分支。
注意,此命令已废弃:fatal: the ‘–set-upstream’ option is no longer supported. Please use ‘–track’ or ‘–set-upstream-to’ instead.
git branch --set-upstream-to=origin/feature-0730 feature-0730
上面命令指定本地feature-0730分支追踪origin/feature-0730分支。

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

git branch -d hotfix 删除hotfix分支

git branch -m oldName newName 重命名本地分支

本地分支重命名(还没有推送到远程)
git branch -m oldName newName

重命名远程分支

若分支已推送到远程,想重命名怎么办?
远程分支重命名 (已经推送远程-假设本地分支和远程对应分支名称相同)
a. 重命名远程分支对应的本地分支
git branch -m oldName newName

b. 删除远程分支
git push –delete origin oldName

c. 上传新命名的本地分支
git push origin newName

d.把修改后的本地分支与远程分支关联
git branch –set-upstream-to origin/newName


git merge

git merge dev 将dev合入当前分支

只需要checkout到你想合并入的分支,然后运行 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 diff

git比较两个分支的文件的差异

git diff branch1 branch2 显示出所有有差异的文件的详细差异

git diff branch1 branch2 –stat 列出2个分支有差异的文件列表

git diff branch1 branch2 文件名(带路径) 显示指定文件的详细差异


git clone

git clone remote_url directory 克隆远程仓库到本地

命令格式:
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/kk/kk.github.io

$ git clone https://github.com/kk/kk.github.io.git
Cloning into 'kk.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 命令会列出已配置的每个远程仓库的简写

git remote -v 列出所有远程仓库url

git remote -v 命令会显示远程仓库的简写与对应的URL:

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

git remote show shortname 查看远程仓库详情

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

$ git remote show origin
* remote origin
  Fetch URL: https://github.com/kk/kk.github.io.git
  Push  URL: https://github.com/kk/kk.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 remote add shortname url 添加远程仓库

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

git remote rm shortname 删除远程仓库

比如想要给项目换个远程仓库,可以先删除当前的origin仓库,再添加新远程仓库
git remote rm origin 删除克隆时自动添加的origin远程仓库


git push

git push origin local:remote 推送到远程仓库

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

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

git push origin local 推送或创建同名远程分支

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

git push origin 推送到追踪的远程分支

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

git push 推送到默认主机的追踪远程分支

如果当前分支与多个主机存在追踪关系,则可以使用-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选项。

git push –set-upstream origin [远程分支名] push时设置追踪关系

git push --set-upstream origin masikkk-dev-0730
将本地分支推送到同名远程分支,同时设置追踪关系

push到GitHub

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

$ git push origin master
Username for 'https://github.com': 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/kk/kk.github.io.git
   4e5e46e..e81605d  master -> master

在GitHub上新建分支

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

git push origin –delete [远程分支名] 删除远程分支

运行带有--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 fetch

拉取远程分支并创建本地分支

使用如下git命令查看所有远程分支:
git branch -r

拉取远程分支并创建本地分支
方法一
使用如下命令:
git checkout -b 本地分支名x origin/远程分支名x
使用该方式会在本地新建分支x,并自动切换到该本地分支x。
采用此种方法建立的本地分支会和远程分支建立映射关系。

方式二
使用如下命令:
git fetch origin 远程分支名x:本地分支名x
如果本地不存在分支x,使用该方式会在本地新建分支x,但是不会自动切换到该本地分支x,需要手动checkout。
采用此种方法建立的本地分支不会和远程分支建立映射关系。

强制远程分支覆盖本地分支

git fetch --all  # fetch所有分支上的内容
git reset --hard origin/master # 重置本地分支,master改为对应分支名
git pull # 拉取远程分支并与本地分支合并

git pull

git pull origin remote:local 拉取远程分支并与本地合并

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

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

git pull origin remote 拉取远程分支与当前本地分支合并

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

git pull origin 拉取有追踪关系的远程分支并合并

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

git pull 拉取唯一追踪的远程分支并合并

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


列出远程分支git branch -a

git branch -a
加上-a参数可以查看远程分支,远程分支会用红色表示出来(如果你开了颜色支持的话)

移除远程仓库

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


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版本控制。


参考


上一篇 Jira及Confluence使用笔记

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

阅读
11,177
阅读预计44分钟
创建日期 2016-04-03
修改日期 2018-09-09
类别
标签
目录
  1. git config
    1. git config -l 列出所有git配置
    2. git配置文件.gitconfig
    3. user.name/user.email 用户信息配置
    4. 不同项目配置不同用户信息
    5. core.autocrlf 换行符自动转换
    6. core.safecrlf 换行符检查
    7. core.quotepath 中文文件名乱码
      1. MAC上git diff/git log中文文件名乱码
    8. credential.helper store存储密码
    9. core.ignorecase文件名大小写敏感配置
      1. 如何修改文件名大小写?
  2. git status
    1. git status查看当前目录中文件状态
    2. git status -s 状态简览
    3. .gitignore 配置忽略文件
      1. .gitignore文件格式
      2. glob模式匹配
  3. git add
    1. git add files跟踪新文件/暂存已修改文件
  4. git rm
    1. git rm file git仓库和本地同时删除
    2. git rm -r 删除目录
    3. git rm -f file 删除暂存区的文件加-f
    4. git rm –cached file git仓库删除但本地保留
    5. 删除git仓库中文件但本地保留
  5. git clean
    1. git clean -f 删除 untracked files
    2. git clean -fd 连 untracked 的目录也一起删掉
    3. git clean -xfd 连 gitignore 的untrack 文件/目录也一起删掉
    4. git clean -nf 显示clean命令要删除的文件
  6. git commit
    1. git commit -a 暂存并提交已跟踪文件
    2. git commit –amend 改写提交
  7. git rebase
    1. git rebase合并整理commit
  8. git log 查看提交历史
    1. git log 倒序查看日志
    2. git log –pretty=oneline 单行显示
  9. git checkout
    1. git checkout [branch-name] 切换分支
    2. git checkout -b 新建并切换到分支
    3. git checkout – file撤销修改
    4. git checkout – . 取消所有本地的修改
    5. git checkout otherBranch files 合并其他分支的指定文件
  10. git reflog 查看commit id
  11. git reset 版本回退
    1. git reset Head 撤销add(暂存)
    2. git reset –hard commit_id 撤销commit并修改代码
    3. git reset commit_id 撤销commit不修改代码
    4. 撤销已commit但未push的修改
    5. 撤销git pull
  12. git branch
    1. git branch 列出所有本地分支
    2. git branch -r 列出所有远程分支
    3. git branch -a 列出所有远程和本地分支
    4. git branch -v 列出所有分支的最后一次提交
    5. git branch [name] 创建分支
    6. git branch –set-upstream-to 设置分支追踪关系
    7. git branch -d [name]删除本地分支
    8. git branch -m oldName newName 重命名本地分支
    9. 重命名远程分支
  13. git merge
    1. git merge dev 将dev合入当前分支
    2. 冲突处理
  14. git diff
    1. git diff branch1 branch2 显示出所有有差异的文件的详细差异
    2. git diff branch1 branch2 –stat 列出2个分支有差异的文件列表
    3. git diff branch1 branch2 文件名(带路径) 显示指定文件的详细差异
  15. git clone
    1. git clone remote_url directory 克隆远程仓库到本地
  16. git remote
    1. git remote 列出所有远程仓库简写
    2. git remote -v 列出所有远程仓库url
    3. git remote show shortname 查看远程仓库详情
    4. git remote add shortname url 添加远程仓库
    5. git remote rm shortname 删除远程仓库
  17. git push
    1. git push origin local:remote 推送到远程仓库
    2. git push origin local 推送或创建同名远程分支
    3. git push origin 推送到追踪的远程分支
    4. git push 推送到默认主机的追踪远程分支
    5. git push –set-upstream origin [远程分支名] push时设置追踪关系
    6. push到GitHub
    7. 在GitHub上新建分支
    8. git push origin –delete [远程分支名] 删除远程分支
  18. git fetch
    1. 拉取远程分支并创建本地分支
    2. 强制远程分支覆盖本地分支
  19. git pull
    1. git pull origin remote:local 拉取远程分支并与本地合并
    2. git pull origin remote 拉取远程分支与当前本地分支合并
    3. git pull origin 拉取有追踪关系的远程分支并合并
    4. git pull 拉取唯一追踪的远程分支并合并
    5. 列出远程分支git branch -a
    6. 移除远程仓库
  20. Git子模块
    1. git clone –recursive 克隆带有子模块的远程仓库
    2. git submodule add 添加子模块
    3. git submodule update –remote 更新子模块
    4. 提交带有子模块的项目
    5. 删除子模块
  21. 参考
百度推荐