git命令行操作详解

时间:2024-08-08 17:03:20

1.常用操作

1.1 新建代码库

# 在当前目录新建一个Git代码库
git init
# 新建一个目录,将其初始化为Git代码库
git init [project-name]
# 下载一个项目和它的整个代码历史
git clone [url]

1.2 配置

# 显示当前的Git配置
git config --list
# 编辑Git配置文件
git config -e [--global]
# 设置提交代码时的用户信息
git config [--global] user.name "[name]"
git config [--global] user.email "[email address]"

1.3 remote管理

# 远程主机名(git要求每个远程主机都必须指定一个主机名,克隆的时候会被自动命名为origin)
git remote
# 如果clone时候想用其它主机名,则加-o选项
git clone -o jQuery https://github.com/jquery/jquery.git
# 查看远程主机网址
git remote -v
# 查看主机详细信息
git remote show origin
# 添加远程主机
git remote add origin https:git.xxxx.git
# 删除远程主机
git remote rm origin
# 远程主机改名
git remote rename origin neworigin

1.4 添加和撤销操作

# 显示有变更的文件
git status
# 该文件内容恢复到上个commit状态
git checkout -- <file>
# 所有文件恢复到上个commit状态
git checkout .
# 修改的该文件放入暂存区
git add <file>
# 所有修改的文件放入暂存区
git add .
# 取消add操作,保留文件的修改
git reset HEAD <file>
# 取消所有的add操作
git reset HEAD .
# 添加commit信息
git commit -m 'your commit message'
#回退所有内容到上一个版本
git reset HEAD^
#向前回退到第3个版本
git reset HEAD~3
# 将本地的状态回退到和远程的一样
git reset origin/master
# 回退到某个版本
git reset 版本号
注意:reset命令有3种方式:
1> git reset –mixed:此为默认方式,不带任何参数的git reset,即时这种方式,它回退到某个版本,只保留源码,回退commit和index信息(需要git add ., git commit -m "xx")
2> git reset –soft:回退到某个版本,只回退了commit的信息,不会恢复到indexfile一级。如果还要提交,直接commit即可(git add . 内容不会丢,可以直接git commit -m "xxx")
3> git reset –hard:彻底回退到某个版本,本地的源码也会变为上一个版本的内容(丢弃所有内容)

1.5 代码提交

# commit信息
git commit -m "first commit"
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
git commit --amend -m [message]
# 本地只是修改commit的信息,没有新的文件更改
git commit --amend "xxxxx"
# 本地修改,但是有新的文件需要添加
git log //找到回退到的版本号xxx
git reset xxx //然后修改文件
git add .
git commit -m "xxx"
# 修改已经提交到远程的commit信息
git commit --amend 'xxx2' //先本地修改commit信息(git reset xxx等方式也可以),然后再强制推上去,慎用
git push --force origin master
# 回退某个文件到某个版本
git log test.php
git reset 9aa51d89799716aa68cff3f30c26f8815408e926 test.php

1.6 分支操作

# 列出所有本地分支
git branch
# 列出所有远程分支
git branch -r
# 列出所有本地分支和远程分支
git branch -a
# 创建分支
git branch test
# 切换分支
git checkout test
# 创建并切换分支
git checkout -b test
# 切换到远程分支
git fetch
git checkout -b test origin/test
# 新建一个分支,指向指定commit
git branch [branch] [commit]
# 新建一个分支,指向某个tag
git checkout -b [branch] [tag]
# 合并指定分支到当前分支
git merge [branch]
# 删除分支(分支已经被合并)
git branch -d [branch-name]
# 删除分支(分支还没合并,强制删除掉)
git branch -D [branch-name]
# 批量删除分支方法
git branch |grep 'branchName' |xargs git branch -D
# 删除远程分支
git branch -dr [origin/test]
git push origin :master
git push origin --delete master
# 选择一个commit,将该commit改动下的代码合并进当前分支
git cherry-pick [commit]

1.7 查看信息

# 显示有变更的文件
git status
# 显示当前分支的版本历史
git log
# 显示commit历史,以及每次commit发生变更的文件
git log --stat
# 显示某个文件的版本历史,包括文件改名
git log --follow [file]
git whatchanged [file]
# 显示指定文件相关的每一次diff
git log -p [file]
# 显示指定文件是什么人在什么时间修改过
git blame [file]
# 显示暂存区和工作区的差异
git diff
# 显示工作区与当前分支最新commit之间的差异
git diff HEAD
# 显示两次提交之间的差异
git diff [first-branch]...[second-branch]
# 显示某次提交的元数据和内容变化
git show [commit]
# 显示某次提交发生变化的文件
git show --name-only [commit]
# 显示某次提交时,某个文件的内容
git show [commit]:[filename]
# 显示当前分支的最近几次提交,可以看到你使用了什么操作
git reflog

1.8 pull操作

# 取回远程主机某个分支的更新,再与本地的指定分支合并
git pull <远程主机名> <远程分支名>:<本地分支名>
# 取回origin主机的next分支,与本地的master分支合并
git pull origin next:master
# 如果远程分支是与当前分支合并,则冒号后面的部分可以省略。
git pull origin next
# 建立追踪关系(git会自动在本地分支和远程分支之间建立一种追踪关系,默认本地分支和远程分支同名,例如next->origin:next)
git branch --set-upstream master origin/next

1.9 push操作

# 把本地库的所有内容推送到远程库上
git push <远程主机名> <本地分支名>:<远程分支名>
# 推送操作,如果省略远程分支名,则表示将本地分支推送与之存在”追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。
git push origin master
# 将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了
git push -u origin master
#不管是否存在对应的远程分支,将本地的所有分支都推送到远程主机
git push --all origin
# 如果远程主机的版本比本地版本更新,推送时Git会报错,要求先在本地做git pull合并差异,然后再推送到远程主机。这时,如果你一定要推送,可以使用--force选项,这样做会覆盖掉远程上比你新的版本。
git push --force origin master

1.10 tag操作

# 展示标签
git tag
# 打标签和注释
git tag -a v0.1.2 -m "0.1.2版本"
# 给指定的commit打标签
git tag -a v0.1.1 9fbc3d0
# git push 操作不会将tag上传到服务器,需要单独上传,将v0.1.2标签提交到git服务器
git push origin v0.1.2
# 将本地所有标签一次性提交到git服务器
git push origin --tags
# 删除标签
git tag -d v0.1.2
# 删除远程的tag
git push origin --delete tag <tagname>

2. 其他一些汇总

2.1 github上初始一个项目

创建一个新的仓库,并上传到github

echo "# ceshi" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin git@github.com:archer-wong/ceshi.git
git push -u origin master

使用一个已有的仓库,并上传到github

git remote add origin git@github.com:archer-wong/ceshi.git
git push -u origin master

2.2 重命名远程分支(先删除远程分支,重命名本地分支,最后提交一个新的远程分支)

git push --delete origin devel
git branch -m devel develop
git push origin develop

2.3 cherry-pick中出现冲突解决方法

git status #查看有哪些冲突
vim xxx.php #手动解决冲突的文件
git add xxx.php
git commit -m "xxx"
git push origin develop

2.4 git中window和Linux换行符问题

不同的操作系统中使用的换行符是不同的,参考如下

Windows/Dos CRLF \r\n
Linux/Unix LF \n
MacOS CR \r

当我们使用git管理版本的时候,如果有人在windows上开发,有人在linux上开发者,很可能你就会遇到行尾结束符问题,可以参考设置以下两项

1> 设置autocrlf

提交时转换为LF,拉取时转换为CRLF(windows上设置)

git config --global core.autocrlf true

提交时转换为LF,拉取时不转换(linux上设置)

git config --global core.autocrlf input

这样可以保证版本库里面是LF换行符,linux上使用LF, windows上迁出后使用的是CRLF

  1. 开启safecrlf检查

Git提供了一个换行符检查功能(core.safecrlf),可以在提交时检查文件是否混用了不同风格的换行符。这个功能的选项如下:

  • false - 不做任何检查
  • warn - 在提交时检查并警告
  • true - 在提交时检查,如果发现混用则拒绝提交

建议使用最严格的 true 选项。core.autocrlf

git config --global core.safecrlf true

2.5 .gitignore文件

.gitignore 配置文件用于配置不需要加入版本管理的文件

1、语法:

所有空行或者以 # 开头的行都会被 Git 忽略。
可以使用标准的 glob 模式匹配。
匹配模式可以以(/)开头防止递归。
匹配模式可以以(/)结尾指定目录。
要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。
星号(*)匹配零个或多个任意字符;
[abc]匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);
问号(?)只匹配一个任意字符;
如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。
使用两个星号(*) 表示匹配任意中间目录,比如a/**/z 可以匹配 a/z, a/b/z 或 a/b/c/z等。

2、示例:

# 忽略 .a 文件
*.a
# 否定忽略 lib.a, 尽管已经在前面忽略了 .a 文件
!lib.a
# 仅在当前目录下忽略 TODO 文件, 但不包括子目录下的 subdir/TODO
/TODO
# 忽略 build/ 文件夹下的所有文件
build/
# 忽略 doc/notes.txt, 不包括 doc/server/arch.txt
doc/*.txt
# 忽略所有的 .pdf 文件 在 doc/ directory 下的
doc/**/*.pdf

GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表,你可以在https://github.com/github/gitignore 找到它.

3、.gitignore不生效问题

如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:

git rm -r --cached .
git add .
git commit -m 'update .gitignore'

2.6 平时采用的git管理模式

平时开发流程,每一个feature新建一个分支,然后在该分支开发完后,进行rebase操作,然后切换到主分支进行merge操作

git branch -b feature-xxx  //在master分支新建并切换分支,在feature-xxx完成代码,然后add,commit
git checkout master
git pull origin master
git checkout feature-xxx
git rebase master
git checkout master
git merge --no-ff feature-xxx
git push origin master

rebase过程中产生冲突的解决方法

查看冲突的文件
git diff
然后手动解决冲突
git status
将冲突文件放入暂存区
git add vendor/composer/autoload_real.php
继续rebase操作
git rebase --continue

2.7 分支合并的总结

参考地址:https://yanhaijing.com/git/2017/07/14/four-method-for-git-merge/

在git中合并分支有三种方法,分别是merge,rebase,cherry-pick,而其中merge又有三种区别fast-forward,no-ff,squash

2.7.1 merge操作

1、fast-forward

如果待合并的分支在当前分支的下游,也就是说没有分叉时,会发生快速合并,从test分支切换到master分支,然后合并test分支

git checkout master
git merge test

这种方法相当于直接把master分支移动到test分支所在的地方,并移动HEAD指针

git命令行操作详解

2、no-ff

如果我们不想要快速合并,那么我们可以强制指定为非快速合并,只需加上--no-ff参数

git checkout master
git merge –no-ff test

这种合并方法会在master分支上新建一个提交节点,从而完成合并

git命令行操作详解

3、squash

svn的在合并分支时采用的就是这种方式,squash会在当前分支新建一个提交节点

squash和no-ff非常类似,区别只有一点不会保留对合入分支的引用

git checkout master
git merge –squash test

git命令行操作详解

2.7.2 rebase操作

当要合并两个分叉的分支时,merge的方式是将待合入分支和当前分支不同的部分,在当前分支新建节点,如下图所示

git命令行操作详解

rebase与merge不同,rebase会将合入分支上超前的节点在待合入分支上重新提交一遍,如下图,B1 B2会变为B1’ B2’,看起来会变成线性历史

git命令行操作详解

2.7.3 cherry-pick

你想把哪个节点merge过来就把哪个节点merge过来,其合入的不是分支而是提交节点