参考来源:https://git-scm.com/book/zh/v2
克隆仓库的命令是 git clone 。 比如,要克隆 Git 的链接库 libgit2:
$ git clone https://github.com/libgit2/libgit2
如果想在克隆远程仓库的时候,自定义本地仓库的名字:
$ git clone https://github.com/libgit2/libgit2 mylibgit
Git 支持多种数据传输协议。 上面的例子使用的是 https:// 协议,不过也可以使用 git:// 协议或者使用 SSH
传输协议,比如 user@server:path/to/repo.git 。
列出指定的远程服务器的简写:
$ git remote
显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL:
$ git remote -v
如果想要查看 origin 远程仓库的更多信息:
$ git remote show 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 重命名为 paul,可以用 git remote rename 这样做:
$ git remote rename pb paul
想要将 pb 重命名为 paul,可以用 git remote rename 这样做:
$ git remote remove paul
从远程仓库中获得数据,可以执行:
$ git fetch pb
必须注意 git fetch 命令只会将数据下载到你的本地仓库——它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。
自动抓取后合并该远程分支到当前分支:
$ git pull
将 master 分支推送到 origin 服务器时:
$ git push origin master
只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先抓取他们的工作并将其合并进你的工作后才能推送。
进入该项目目录:
$ git init
该命令将创建一个名为 .git 的子目录,这个子目录含有初始化的 Git 仓库中所有的必须文件。
但是,在这个时候,项目里的文件还没有被跟踪。
git add 添加所有需要的文件(注意之后新建文件都要 git add 追踪),然后commit:
$ git add *.c
$ git add LICENSE
$ git commit -m 'initial project version'
在项目下创建一个新的 README 文件。 如果之前并不存在这个文件,使用 git status 命令,你将看到一个新的未跟踪文件:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
(use "git add ..." to include in what will be committed)
README
nothing added to commit but untracked files present (use "git add" to track)
追踪之后:
$ git add README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git restore --staged ..." to unstage)
new file: README
简短输出:
$ git status -s
或者
$ git status --short
查看尚未暂存的文件更新了哪些部分:
$ git diff
查看已暂存的将要添加到下次提交里的内容,比对已暂存文件与最后一次提交的文件差异:
$ git diff --staged
或者
$ git diff --cached
git log 有很多参数可选,详细看这里。
$ git log
提交之前,请确认还有什么已修改或新建的文件还没有 git add 过:
$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'
在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤:
$ git commit -a -m 'added new benchmarks'
提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
最终只会有一个提交——第二次提交将代替第一次提交的结果。
修改提交信息,只能是最后一次的提交:
git commit --amend -m "新的修改提交信息"
取消暂存的文件,就是不放置到要提交的commit中:
$ git reset HEAD CONTRIBUTING.md
可以通过 git status 获得提示
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
renamed: README.md -> README
modified: CONTRIBUTING.md
取消上一次的commit,仅仅是撤回commit操作,修改的代码仍然保留。
注意:这里是没有push过的commit!!!
git reset --soft HEAD^
HEAD^的意思是上一个版本,也可以写成HEAD~1 如果进行了2次commit,想都撤回,可以使用HEAD~2
--mixed
:不删除工作空间改动代码,撤销commit,并且撤销git add . ,这个为默认参数;
--soft
:不删除工作空间改动代码,撤销commit,不撤销git add . ;
--hard
:删除工作空间改动代码,撤销commit,撤销git add . 。
如果已经push到远程的分支(比如origin/example)
先git log查看commit的ID:
$ git log
commit ca2222222222222(HEAD -> example)
Author: xxx
Date: Wed Jul 31 10:50:21 2021 +0800
错误的提交
commit 5a11111111111111
Author: xxx
Date: Wed Jul 28 10:50:21 2021 +0800
最近一次正确的提交
要撤销那个“错误的提交”,就是ID为ca2222222222222的,就需要先在本地回退到5a11111111111111:
git reset --soft 5a11111111111111
再次查看log,会发现本地是:
$ git log
commit 5a11111111111111(HEAD -> example)
Author: xxx
Date: Wed Jul 28 10:50:21 2021 +0800
最近一次正确的提交
远程是没有变化的:
$ git log origin/example
commit ca2222222222222(origin/example)
Author: xxx
Date: Wed Jul 31 10:50:21 2021 +0800
错误的提交
commit 5a11111111111111
Author: xxx
Date: Wed Jul 28 10:50:21 2021 +0800
最近一次正确的提交
然后强制推送:
git push origin HEAD--force
或者
git push origin example--force
再次查看远端log就会发现那个错误的commit不见了。
撤消修改——将它还原成上次提交时的样子:
$ git checkout -- CONTRIBUTING.md
可以通过 git status 获得提示:
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: CONTRIBUTING.md
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交:
$ git rm log/\*.log
注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。 此命令删除 log/ 目录下扩展名为 .log 的所有文件。 类似的比如:
$ git rm \*~
该命令会删除所有名字以 ~ 结尾的文件。
想让文件保留在磁盘,但是并不想让 Git 继续跟踪:
$ git rm --cached README
相当于重命名:
$ git mv file_from file_to
运行 git mv 就相当于运行了下面三条命令:
$ mv README.md README
$ git rm README.md
$ git add README
创建一个 testing 分支:
$ git branch testing
切换到新创建的 testing 分支:
$ git checkout testing
在 Git 中,有一个名为 HEAD 的特殊指针,指向当前所在的本地分支(注:将 HEAD 想象为当前分支的别名)。
切换后
新建一个分支并同时切换到那个分支上,做一点修改:
$ git checkout -b iss53
将 hotfix 分支合并回 master 分支来部署到线上:
$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
当你试图合并两个分支时, 如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,
只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。
参考
将指定的commit(id是31206425457abbb5ee367138cee4239747d727ba的提交)应用于其他分支(切换到的当前分支):
git cherry-pick 31206425457abbb5ee367138cee4239747d727ba
git cherry-pick命令的参数,不一定是提交的哈希值,分支名也是可以的,表示转移该分支的最新提交。
如果想要转移一系列的连续提交,可以使用下面的简便语法。
git cherry-pick A..B
上面的命令可以转移从 A 到 B 的所有提交。它们必须按照正确的顺序放置:提交 A 必须早于提交 B,否则命令将失败,但不会报错。
注意,使用上面的命令,提交 A 将不会包含在 Cherry pick 中。如果要包含提交 A,可以使用下面的语法:
git cherry-pick A^..B
参考
合并的时候可能有冲突,需要先贮存:
git stash
然后从栈中将刚才贮藏的冲突取出来,这时候会把放在栈中的代码合并到本地,在CodeEnum中就会出现冲突:
git stash pop
删除分支 hotfix :
$ git branch -d hotfix
将提交到某一分支上的所有修改都移至另一分支上,就好像“重新播放”一样:
$ git checkout experiment
$ git rebase master
merge与rebase的区别
merge是这样
rebase
最后再进行一下master快进
$ git checkout master
$ git merge experiment
查看每一个分支的最后一次提交:
$ git branch -v
从服务器上删除 serverfix 分支:
$ git push origin --delete serverfix
参考
获取远程仓库origin的指定分支remote_branch,并创建与之关联的本地分支local_branch(建议同名,便于管理):
git fetch origin remote_branch_name:local_branch
先git log获取要还原到的版本的id,比如
然后:
git reset --hard 40b31300d199fe96131409dad1421e5a7d4275f0
强制推送远程分支:
git push -f
要撤回某个已经pull的提交,使用“git revert -n 版本号”命令:
git revert -n 40b31300d199fe96131409dad1421e5a7d4275f0
注意: 这里可能会出现冲突,那么需要手动修改冲突的文件。
然后再提交:
git commit -m "提交信息-撤回40b3130xxx的提交"
注意reset和revert的区别
参考
放弃本地的修改,强制将本地和远程的origin/master同步:
git fetch --all
git reset --hard origin/master
git pull
使用 git submodule add 添加子模块,url为子模块的路径,path为该子模块存储的目录路径。例子里面添加了一个叫DbConnector的子模块
git commit -m 和 git commit -am的区别
git submodule add https://github.com/chaconinc/DbConnector
git commit -am 'added DbConnector module'
git push origin master
默认情况下,子模块会将子项目放到一个与仓库同名的目录中,本例中是 “DbConnector”。 如果想要放到其他地方,那么可以在命令结尾添加一个不同的路径。
虽然 DbConnector 是工作目录中的一个子目录,但 Git 还是会将它视作一个子模块。不在那个目录中时,Git 并不会跟踪它的内容, 而是将它看作子模块仓库中的某个具体的提交。
克隆一个含有子模块的项目,默认会包含该子模块目录,但其中还没有任何文件:
git clone https://github.com/chaconinc/MainProject
其中有 DbConnector 目录,不过是空的,需要初始化和更新,先要进入当前文件下:
cd DbConnector/
git submodule init
git submodule update
直接使用下面的语句可以一步到位(初始化加更新):
git clone --recurse-submodules https://github.com/chaconinc/MainProject
如果你已经克隆了项目但忘记了 --recurse-submodules,那么可以运行:
git submodule update --init
将 git submodule init 和 git submodule update 合并成一步。
如果还要初始化、抓取并检出任何嵌套的子模块, 请使用:
git submodule update --init --recursive
进入子模块的目录中运行 git fetch 与 git merge,合并上游分支来更新本地代码:
git fetch
git merge origin/master
返回到主项目查看:
git diff --submodule
如果不想在子目录中手动抓取与合并,一步到位的方法:
git submodule update --remote DbConnector
此命令默认会假定你想要更新并检出子模块仓库的 master 分支。
设置其他分支。 例如,你想要 DbConnector 子模块跟踪仓库的 “stable” 分支,那么既可以在 .gitmodules 文件中设置 (这样其他人也可以跟踪它),也可以只在本地的 .git/config 文件中设置。 让我们在 .gitmodules 文件中设置它:
git config -f .gitmodules submodule.DbConnector.branch stable
如果不用 -f .gitmodules 选项,那么它只会为你做修改。但是在仓库中保留跟踪信息更有意义一些,因为其他人也可以得到同样的效果。
进入子模块所在的位置然后切换分支即可:
cd DbConnector/
git checkout stable
更新子模块:
git submodule update --remote --merge
或者
git submodule update --remote --rebase
最后提一句详细文档是
这个
上面的内容是摘取了改文档里面的最常用基础的内容。
Git push 时如何避免出现 “Merge branch ‘master’ of …”
Git分支合并冲突解决