git命令
首次git
#设置用户名
git config –global user.name 用户名
#设置邮箱名
git config –global user.email 邮箱地址
#验证密匙
less ~/.ssh/id_rsa.pub
#添加密匙
ssh-keygen -t rsa -C 邮箱地址
#克隆仓库
git clone
#初始化本地仓库
git init
#添加本地所有文件到仓库
git add -A
#添加commit
git commit -m "blog源文件"
#创建并切换到分支(以当前分支为base)
git checkout -b hexo
#添加远程仓库,origin就是你为远端仓库所起的名字,git@github.com:XXX/YYY.git就是你的远端仓库的真实地址;
git remote add origin git@github.com:XXX/YYY.git
#第一次推送到远程仓库,origin是仓库名,master是分支名,加了参数-u后,以后即可直接用git push 代替git push origin master
git push -u origin master
git 配置文件:~/.gitconfig
代码提交
#备份差分文件
#拉取远程仓库并插分
git pull
#差分要更新的文件
#查看仓库状态,也可以用 git diff
git status
#将需要打包的文件加入暂存区
git add <file>
#也可以将忽略文件列表放到.gitignore文件中,添加本地所有文件到仓库
git add -A
# 删除暂存区文件
git rm <file>
#提交代码并添加评论
git commit -m "blog源文件"
#将本地仓库的源文件推送到远程仓库hexo分支
git push origin hexo
#版本硬回退,直接删除掉目标HEAD之后所有的操作,且工作去和暂存区都会修改。
git reset --hard 版本号
#硬回退到上次提交状态
git reset --hard HEAD^
git reset --hard HEAD~3
#版本软回退,会将工作去的文件回退到目标版本,但是不会改变暂存区的状态。
git reset --soft 版本号
#查看提交历史
git log
#查看命令历史
git reflog
#删除文件
git rm <file>
git config --global alias.st status #配置别名
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit" #格式化查看log
子模块
#初始化并递归更新/拉取子模块
git submodule update --init --recursive
#添加子模块
git submodule add 链接 文件夹
分支与合并
#查看分支
git branch -v
#查看所有分支
git branch -a
#创建分支dev
git branch dev
#切换分支
git checkout <branch name>
#创建并切换到本地分支nweBranch
git checkout -b nweBranch
#将本地新分支nweBranch推送到远程
git push origin nweBranch
#设置本地分支跟踪远程分支,如果不设置更新,smartgit不能pull
git branch --set-upstream-to=origin/nweBranch
#查看本地分支和远程分支的映射关系
git branch -vv
#查看远程分支
git branch -r
#创建分支
git branch 分支名
#删除分支
git branch -d 分支名
#删除远程分支
git push origin --delete 分支名
#假如,你完成了一个新功能的开发,你想要把这个功能整合到你的 “产品” 分支中去。或者相反的流程,你正在一个分支中开发这个新的功能,同时在你所开发项目中发生了一些改变(比如一些严重的错误被修复了),你很需要这些改动也能被整合到你正在使用的分支中。
#无论是哪一种情况我们都称这种整合叫做 “合并(merging)”。在 Git 中我们使用 “git merge” 命令来进行合并的操作。
#切换到那个需要接收改动的分支上。
git checkout master
#执行 “git merge” 命令,并且在后面加上那个将要合并进来的分支的名称,这样,dev分支的改动就会被整合提交给master分支了
git merge dev
冲突
首先你应该记住,你总是可以撤销一个合并操作,并且返回到冲突发生之前的状态。也就是说,你永远有机会放弃并重新开始。
当你使用 “git status” 时, Git 会告诉你存在一个 “未合并的路径(unmerged paths)”,这只是用另外一个方式告诉你,存在一个或多个冲突。你可以编辑这些文件,冲突部分会像这样:
<<<<<< HEAD
This line was committed while working in the "login-box" branch.
========
This line,incontrast,was commited while working in the "contact-form" branch.
>>>>>> refs/heads/contact-form
第一个标记后的内容源于当前分支。在尖括号之后,Git 会告诉我们这些改动是从哪里(哪个分支)来的。然后有冲突的改动会被 “=======” 分割起来。
现在我们的工作是要清理这些问题行。当我们完成这些清理后,执行 “git add” 命令。这也标志着冲突已经解决了。
快速解决冲突
git checkout --ours <file> #使用当前分支文件
git checkout --theirs <file> # 使用需要被合并的分支文件
撤销一个合并
只要在命令行界面中键入 “git merge --abort” 命令,你的合并操作就会被安全的撤销。
当你解决完冲突,并且在合并完成后发现一个错误,你仍然还是有机会来简单地撤销它。你只须要键入 “git reset --hard ” 命令,系统就会回滚到那个合并开始前的状态,然后重新开始吧!
Ps:Git 除了用merge来做简单的整合改动,还可以用rebase来实现共同原始提交。rebase中ours和theirs的定义与merge完全相反,有兴趣的同学可以自己了解一下
打标签
Git 可以给历史中的某一个提交打上标签,以示重要。 比较有代表性的是人们会使用这个功能来标记发布结点(v1.0 等等)。
#列出标签
git tag
#Git 使用两种主要类型的标签:轻量标签(lightweight)与附注标签(annotated)。
#附注标签
git tag -a v1.4 -m 'my version 1.4'
#轻量标签
git tag v1.4-lw
远程仓库
开发团队的其他成员在你们共同的远程仓库上共享了他的改动,在这些改动被整合到你的本地副本之前,你需要首先要检查一下这些改动:
git fetch <remote name>
git log <remote name>/<branch name>
如果你决定要整合这些改动到你的本地副本中来, 你就可以使用 “git pull” 命名来完成这个操作:
git pull
将一个本地分支发布到远程仓库:
git push -u <remote name> <branch name>
撤销
修改最后一次提交
当你认为提交有问题时,你都可以使用 “git commit” 命令,并附带上 “--amend” 参数,这个操作可以非常轻松地来修改你的_最后一次_提交。
如果你仅仅是想修改上一次的提交注释,你并不需要操作暂存区,简单地再次输入 “git commit --amend” 并附带上正确的注释就可以了:
git commit --amend -m "This is the correct message"
如果你想要添加更多的改动到上一次提交中,你可以像平常一样把这些新的改动添加到暂存区。然后再次使用 “--amend” 参数进行提交:
git add some/changed/file.ext
git commit --amend -m "commit message"
- 不要修改已经被发布的提交!!!!
- 撤销本地改动
当改动还没有被提交之前,它们仍然被称之为 “本地” 改动,恢复一个文件到上次提交之后的状态,你可以使用 “git checkout”命令:
git checkout -- file/to/restore.ext
如果你想要放弃你在工作副本(working copy)中的所有本地改动,并让你的本地副本恢复到上次提交之后的版本,你可以使用 “git reset” 命令:
git reset --hard HEAD
撤销已提交的改动
使用 “git revert” 命令可以撤销某个之前的提交。但是这个命令并不是删除那个提交,相反的,它是恢复那个提交的改动,这只是看起来像是撤销而已。
git revert 2b504be
回滚
使用“git reset” 命令不会自动产生一个新的提交,或是删除你要撤销的提交,它会重置你当前的 HEAD 分支到一个特定旧的版本
git reset --hard 2be18d9
其他
主库相当于目录,因此git提交代码后还需要提交一遍子库,而下载时,现在的是主库,也就是目录,空文件夹,因为还需要下载子库.
在Git中,用HEAD
表示当前版本,也就是最新的提交版本,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100
。
工作区-暂存区-版本库
当前工作文件夹叫做工作区,
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
每次修改,如果不用git add到暂存区,那就不会加入到commit中。
像这样,你不断对文件进行修改,然后不断提交修改到版本库里,就好比玩RPG游戏时,每通过一关就会自动把游戏状态存盘,如果某一关没过去,你还可以选择读取前一关的状态。有些时候,在打Boss之前,你会手动存盘,以便万一打Boss失败了,可以从最近的地方重新开始。Git也是一样,每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作,而不是把几个月的工作成果全部丢失。
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
用git log --graph
命令可以看到分支合并图。
忽略某些文件时,需要编写.gitignore;
执行命令后,没有任何显示,这就对了,Unix的哲学是“没有消息就是好消息”,说明添加成功。
git pull=git fetch + git merge
git fetch是拉取,git merge是合并
reserv和reset
reset是移动head指针,且该版本之后的commit不会出现。
revert是重做某一个版本,且不改变此版本之后的提交。
Git 一共有3个配置文件:
- 仓库级的配置文件:在仓库的 .git/.gitconfig,该配置文件只对所在的仓库有效。
- 全局配置文件:Mac 系统在 ~/.gitconfig,Windows 系统在 C:\Users<用户名>.gitconfig。
- 系统级的配置文件:在 Git 的安装目录下(Mac 系统下安装目录在 /usr/local/git)的 etc 文件夹中的 gitconfig。
--local:仓库级,--global:全局级,--system:系统级
子模块
经常有这样的事情,当你在一个项目上工作时,你需要在其中使用另外一个项目。也许它是一个第三方开发的库或者是你独立开发和并在多个父项目中使用的。这个场景下一个常见的问题产生了:你想将两个项目单独处理但是又需要在其中一个中使用另外一个。
这里有一个例子。假设你在开发一个网站,为之创建Atom源。你不想编写一个自己的Atom生成代码,而是决定使用一个库。你可能不得不像CPAN install或者Ruby gem一样包含来自共享库的代码,或者将代码拷贝到你的项目树中。如果采用包含库的办法,那么不管用什么办法都很难去定制这个库,部署它就更加困难了,因为你必须确保每个客户都拥有那个库。把代码包含到你自己的项目中带来的问题是,当上游被修改时,任何你进行的定制化的修改都很难归并。
Git 通过子模块处理这个问题。子模块允许你将一个 Git 仓库当作另外一个Git仓库的子目录。这允许你克隆另外一个仓库到你的项目中并且保持你的提交相对独立。
smartgit提交流程
smartgit是一款全平台图形化git工具。
使用smartgit的代码提交流程如下:
1.备份
备份要提交的文件,防止弄错后无法挽回
2.设置分支
确认当前文件的包是不是master,如果不是master,
则在所在仓库check out变成master,
然后pull拉取代码为最新
3.提交
选择要提交的文件,
commit,
填写log,
切换分支,提交其他代码
切换分支时多数要merge并处理冲突。
可以多次commit,然后一次push to,
但是每次commit只能提交同一个子库的文件。
4.推送
Push默认推送到master
Push to可以选择推送分支,
例如:Push to: refs/for/master
此时如出现以下错误:
BUG:
remote: ERROR: [2883a2e] missing Change-Id in commit message footer
remote:
remote: Hint: To automatically insert Change-Id, install the hook:
remote: gitdir=$(git rev-parse --git-dir); scp -p -P 29418 chen_dq@10.10.88.49:hooks/commit-msg ${gitdir}/hooks/
remote: And then amend the commit:
remote: git commit --amend
remote:
error: failed to push some refs to 'ssh:#chen_dq@10.10.88.49:29418/integration/EHP-Navi-dev'
则按照Hint的提示来操作,首先将版本回退,在左侧master上右键Reset,或者在下方列表中的版本上右键Reset
然后在将要提交的文件的所在包内git bash here,
按照提示执行类似操作:
gitdir=$(git rev-parse --git-dir)
scp -p -P 29418 chen_dq@10.10.88.49:hooks/commit-msg ${gitdir}/hooks/
然后reset撤回上次提交,
然后重新commit,然后重新push to就成功了。
5.审阅
此处需要管理员操作,
打开gerrit,
ALL-Open,
打开提交的代码,
review,
如果正确,
提交。
6.提交子库
在子库上Pull更新代码,
当子库没有箭头时代表更新成功。
上箭头表示服务器比本地版本高,下箭头表示本地比服务器版本高
子库的节点可以同时commit,然后pushto,review。
术语
HEAD
这要从git的分支说起,git 中的分支,其实本质上仅仅是个指向 commit 对象的可变指针。git 是如何知道你当前在哪个分支上工作的呢?
其实答案也很简单,它保存着一个名为 HEAD 的特别指针。在 git 中,它是一个指向你正在工作中的本地分支的指针,可以将 HEAD 想象为当前分支的别名。
参考链接:
https://blog.sina.com.cn/s/blog_dc9540b00102x0z4.html
https://www.liaoxuefeng.com/wiki/896043488029600
https://blog.csdn.net/yxlshk/article/details/79944535
https://git-scm.com/book/zh/v1/Git-工具-子模块