git使用说明

目录

前言

以前一直用subversion,使用图形界面,用了好几年,后来公司要求转git,别人一月就转变过来了,我一年后才转换过来,寻找各种教程,尝试各种工具.最终发现引领我入门的是官网的Pro git,而最终选择的工具是直接使用命令行.

这是我常用的命令行使用手册,当时迷茫的是命令行太多,哪些是我需要的呢?怎样使用git命令代替我使用subversion通过界面进行操作.基于这两点考虑,我总结了一些使用场景我常用的命令,这些命令我也记不住,在使用的过程中打开我这篇手册,忘记的操作立马查看,只要记得使用场景就可以了,然后慢慢简单使用的命令代替场景下的命令.慢慢优化形成了这本手册,其实子模块使用很少,没有进行命令优化,可以不学习子模块,代替子模块比较好的方案是使用repo.

1.安装

1.1. windows

1.1.1.git客户端

在网站https://git-scm.com/ 下载最新版的git客户端进行安装。
安装时,一直next就可以了。

1.1.2.配置git客户端

配置如下:

bash 复制代码
git config --global user.name "fedorayang"
git config --global user.email "fedorayang@163.com"
git config --global --bool http.sslVerify true
git config --global branch.autosetuprebase always
git config --global credential.helper store
git config --global core.quotepath false
git config --global core.filemode false

查看当前的配置

bash 复制代码
git config --list

user.name,user.email每次提交时,在log中都会体现,用于标识提交者和联系方式。

这几个配置选项一定要配置。

1.1.3.安装TortoiseGit图形客户端

Git使用建议使用命令行,其实图形客户端使用起来也非常方便。

https://tortoisegit.org/ 下载最新的客户端,

安装时,一直next就可以了。

查看是否安装成功。

1.1.4 关于文件换行问题

Dos和Windows平台: 使用回车(CR)和换行(LF)两个字符来结束一行,回车+换行(CR+LF),即"\r\n";

Mac 和 Linux平台:只使用换行(LF)一个字符来结束一行,即"\n";

最早Mac每行结尾是回车CR 即'\r',后mac os x 也投奔了 unix。

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

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

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

你也可以在文件提交时进行safecrlf检查

bash 复制代码
#拒绝提交包含混合换行符的文件
git config --global core.safecrlf true   
 
#允许提交包含混合换行符的文件
git config --global core.safecrlf false   
 
#提交包含混合换行符的文件时给出警告
git config --global core.safecrlf warn

1.2.ubuntu

bash 复制代码
sudo apt install git-all

安装git所有相关

1.2.1.ubuntu终端Git中文乱码

ubuntu终端Git中文乱码:200\273\347\273\223

使用git add添加要提交的文件的时候,显示形如2200\273\347\273\223乱码。

解决方案:

bash 复制代码
git config --global core.quotepath false

1.2.2 git log中文乱码解决

1.运行Git Bash窗口,在该窗口导航条(即最上面)右键,选择Options−>Text,找到下面两处:

Locale: zh_CN
Charector set: UTF-8

2.到Git Bash命令窗口输入如下设置命令语句

bash 复制代码
#该命令表示提交命令的时候使用utf-8编码集提交
git config --global i18n.commitencoding utf-8
#该命令表示日志输出时使用utf-8编码集显示
git config --global i18n.logoutputencoding utf-8
#设置LESS字符集为utf-8
export LESSCHARSET=utf-8

设置完成后,发现使用git log后,之前提交代码的中文注释正确显示出来.

2.建立版本库

建立版本库根据使用场景不同有几种方式:下载网上开源版本库,自己创建本地版本库,在服务器上创建版本库。

2.1.下载网上开源版本库

使用浏览器开源项目,例如https://source.denx.de/u-boot/u-boot

2.1.1.复制下载地址

2.1.2.使用命令行下载库

打开git命令行窗口

输入 git clone https://source.denx.de/u-boot/u-boot.git 。 会自动下载,等待下载完成。

2.1.3.使用图形界面下载库

复制git仓库地址后,可以使用torroiseGit下载仓库


2.2.在当前目录初始化版本库

2.2.1.命令行方式创建

bash 复制代码
#初始化版本
git init
#把当前工作区内容添加到版本库
git add
#提交到仓库
git commit

2.2.2.GUI方式创建


3.基本操作

3.1.忽略某些文件

.gitignore

3.2.保留一些空目录

touch .gitkeep

3.3.提交到本地

git status
git add
git commit

3.4.查看差异和日志

git log -p -2
git diff

3.5.远程仓库

3.5.1查看当前的远程库

git remote
git remote -v

3.5.2.添加远程仓库

git remote add [shortname] [url]

3.5.3.从远程仓库抓取数据

bash 复制代码
git fetch [remote-name]

3.5.4.推送数据到远程仓库

bash 复制代码
git push [remote-name] [branch-name]
#创建远程分支并推送
git push -u [remote-name] [branch-name]

3.5.5.查看远程仓库信息

git remote show [remote-name]

3.5.6.远程仓库的删除和重命名

git remote rename pb paul
git remote rm paul

3.5.7.更改远程仓库服务器地址

git remote origin set-url [url]

3.5.8.远程仓库版本回退

git push <仓库名> <分支名> -f

3.5.9.远程仓库删除后更新到本地

git remote prune origin
git branch -a

3.6.远程分支

3.6.1.推送

git push origin serverfix
git push origin refs/heads/serverfix:refs/heads/serverfix
[local] [remote]
git push origin serverfix:serverfix
git push origin serverfix:awesomebranch

3.6.2.查看远程分支

git fetch origin
或者
git fetch
git branch -a

3.6.3.合并到当前分支

git merge origin/serverfix

3.6.4.建立新的本地分支

git checkout -b serverfix origin/serverfix
或者
git checkout --track origin/serverfix

3.6.5.获取数据

git pull
git fetch 和 git merge origin/serverfix

3.6.6.推送数据

git push

3.6.7.删除远程分支

git push origin :serverfix

3.7.本地分支操作

3.7.1.建立分支

git branch onebranch 建立新的分支
git checkout --b secondbrach 建立新的分支名跳转到新分支

3.7.2.查看所有分支

git branch --a

3.7.3.切换分支

git checkout somebranch

3.7.4.删除分支

git branch --d somebranch

3.8.检出以前的版本

3.8.1. 根据sha值建立分支

git log 获取历史版本的sha值

git branch oldver 05984e59d8 根据sha值建立分支

使用过后,删除临时分支

3.8.2.临时检出版本

git log 获取历史版本的sha值
git checkout 05984e59d8 -- . 检出历史版本
使用过后恢复最新版本版本
git reset HEAD .
git checkout -- .
git clean --df

3.9.打标签和推送标签

对于发布的软件版本需要打上标签,方便管理

git tag -a v1.0.0
git push origin v1.0.0

3.10.分支管理

Git管理流程有许多种,这里推荐流程如下:

参考文档 http://roclinux.cn/?p=2129#more-2129

开源实现可以参考这个

https://github.com/petervanderdoes/gitflow-avh

4.子模块

4.1.添加子模块

bash 复制代码
#在主仓库执行
git submodule add https://gitee.com/fedorayang/sumodule_sub1.git
#默认情况下,子模块会将子项目放到一个与仓库同名的目录中,本例中是"sumodule_sub1".
tree
sumodule_main/
├── README.md
└── sumodule_sub1
    └── README.md
bash 复制代码
#如果你想要放到其他地方,那么可以在命令结尾添加一个不同的路径.
git submodule add https://gitee.com/fedorayang/sumodule_sub2.git extern
tree
sumodule_main/
├── extern
│   └── README.md
├── README.md
└── sumodule_sub1
    └── README.md
ini 复制代码
git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   .gitmodules
	new file:   extern
	new file:   sumodule_sub1

.gitmodules文件内容:

ini 复制代码
[submodule "sumodule_sub1"]
        path = sumodule_sub1
        url = https://gitee.com/fedorayang/sumodule_sub1.git
[submodule "extern"]
        path = extern
        url = https://gitee.com/fedorayang/sumodule_sub2.git

该配置文件保存了项目 URL 与已经拉取的本地目录之间的映射.

bash 复制代码
#通过在本地执行 
git config submodule.extern.url <私有URL> 
#来覆盖这个选项的值

查看差异.

bash 复制代码
git diff --cached
git diff --cached --submodule
bash 复制代码
git commit #提交
git push origin master #推送

4.2.克隆含有子模块的项目

分步进行

bash 复制代码
git clone https://gitee.com/fedorayang/sumodule_main.git
#当你在克隆这样的项目时,默认会包含该子模块目录,但其中还没有任何文件.
tree sumodule_main/
sumodule_main/
├── extern
├── README.md
└── sumodule_sub1

初始化本地配置文件

bash 复制代码
git submodule init
Submodule 'extern' (https://gitee.com/fedorayang/sumodule_sub2.git) registered for path 'extern'
Submodule 'sumodule_sub1' (https://gitee.com/fedorayang/sumodule_sub1.git) registered for path 'sumodule_sub1'

从该项目中抓取所有数据检出父项目中列出的合适的提交

bash 复制代码
git submodule update
Cloning into '/home/git_test/sumodule_main/extern'...
Cloning into '/home/git_test/sumodule_main/sumodule_sub1'...
Submodule path 'extern': checked out '855083d4a426763ab36c0e0dde3218591e332b08'
Submodule path 'sumodule_sub1': checked out 'c6982e7d3a6b18e016d589ee234a04941e776b5a'

现在子目录是处在和之前提交时相同的状态了。

一步完成

git clone --recurse-submodules https://gitee.com/fedorayang/sumodule_main.git single_step

如果你已经克隆了项目但忘记了 --recurse-submodules,那么可以运行 git submodule update --initgit submodule initgit submodule update 合并成一步。

如果还要初始化、抓取并检出任何嵌套的子模块, 请使用简明的 git submodule update --init --recursive

4.3.在包含子模块的项目上工作

4.3.1.从子模块的远端拉取上游修改

分步实现

bash 复制代码
#1.进入到子模块目录
#2.拉取
git fetch
#3.合并
git merge origin/master

如果你现在返回到主项目并运行 git diff --submodule,就会看到子模块被更新的同时获得了一个包含新添加提交的列表。

bash 复制代码
git diff --submodule
Submodule sumodule_sub1 c6982e7..a43342c:
  > hello

如果你不想每次运行 git diff 时都输入 --submodle,那么可以将 diff.submodule 设置为 "log" 来将其作为默认行为。

bash 复制代码
git config --global diff.submodule log
git diff
Submodule sumodule_sub1 c6982e7..a43342c:
  > hello

如果在此时提交,那么你会将子模块锁定为其他人更新时的新代码。

单步实现

如果你不想在子目录中手动抓取与合并,那么还有种更容易的方式。 运行 git submodule update --remote,Git 将会进入子模块然后抓取并更新。

bash 复制代码
git submodule update --remote

此命令默认会假定你想要更新并检出子模块仓库的 master 分支。

子模块其他分支

不过你也可以设置为想要的其他分支。既可以在 .gitmodules 文件中设置 (这样其他人也可以跟踪它),也可以只在本地的 .git/config 文件中设置。

bash 复制代码
git config -f .gitmodules submodule.sumodule_sub1.branch develop
git submodule update --remote

如果不用 -f .gitmodules 选项,那么它只会为你做修改。但是在仓库中保留跟踪信息更有意义一些,因为其他人也可以得到同样的效果。

查看信息

这时我们运行 git status,Git 会显示子模块中有"新提交"。

bash 复制代码
git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   extern
	modified:   sumodule_sub1

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   .gitmodules
	modified:   sumodule_sub1 (new commits)

如果你设置了配置选项 status.submodulesummary,Git 也会显示你的子模块的更改摘要:

bash 复制代码
git config status.submodulesummary 1
git status

On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   extern
	modified:   sumodule_sub1

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   .gitmodules
	modified:   sumodule_sub1 (new commits)

Submodule changes to be committed:

* extern 855083d...31954ce (1):
  > init

* sumodule_sub1 c6982e7...a43342c (1):
  > hello

Submodules changed but not updated:

* sumodule_sub1 a43342c...35c50c4 (1):
  > develop

这时如果运行 git diff,可以看到我们修改了 .gitmodules 文件,同时还有几个已拉取的提交需要提交到我们自己的子模块项目中。

bash 复制代码
git diff

这非常有趣,因为我们可以直接看到将要提交到子模块中的提交日志。 提交之后,你也可以运行 git log -p 查看这个信息。

bash 复制代码
git log -p --submodule

更新单个子模块

当运行 git submodule update --remote 时,Git 默认会尝试更新 所有 子模块, 所以如果有很多子模块的话,你可以传递想要更新的子模块的名字。

4.3.2.从项目远端拉取上游更改

只是执行 git pull 获取你新提交的更改还不够,应该使用

bash 复制代码
git submodule update --init --recursive
#或者
git pull --recurse-submodules

可以将配置选项 submodule.recurse 设置为 true,此选项会让 Git 为所有支持 --recurse-submodules 的命令使用该选项(除 clone 以外)。

子模块的 URL 发生了改变

bash 复制代码
# 将新的 URL 复制到本地配置中
git submodule sync --recursive
# 从新 URL 更新子模块
git submodule update --init --recursive

4.4.在子模块上工作

首先,让我们进入子模块目录然后检出一个分支。

bash 复制代码
cd DbConnector/
git checkout stable
Switched to branch 'stable'

然后尝试用 "merge" 选项来更新子模块。 为了手动指定它,我们只需给 update 添加 --merge 选项即可。 这时我们将会看到服务器上的这个子模块有一个改动并且它被合并了进来。

bash 复制代码
cd ..
git submodule update --remote --merge

现在让我们看看当我们对库做一些本地的改动而同时其他人推送另外一个修改到上游时会发生什么。

如果我们现在更新子模块,就会看到当我们在本地做了更改时上游也有一个改动,我们需要将它并入本地。

bash 复制代码
git submodule update --remote --rebase

如果你忘记 --rebase--merge,Git 会将子模块更新为服务器上的状态。并且会将项目重置为一个游离的 HEAD 状态。

即便这真的发生了也不要紧,你只需回到目录中再次检出你的分支(即还包含着你的工作的分支)然后手动地合并或变基 origin/stable(或任何一个你想要的远程分支)就行了。

4.4.1发布子模块改动

如果我们在主项目中提交并推送但并不推送子模块上的改动,其他尝试检出我们修改的人会遇到麻烦, 因为他们无法得到依赖的子模块改动。那些改动只存在于我们本地的拷贝中。

为了确保这不会发生,你可以让 Git 在推送到主项目前检查所有子模块是否已推送。 git push 命令接受可以设置为 "check" 或 "on-demand" 的 --recurse-submodules 参数。 如果任何提交的子模块改动没有推送那么 "check" 选项会直接使 push 操作失败。

bash 复制代码
git push --recurse-submodules=check
The following submodule paths contain changes that can
not be found on any remote:
  DbConnector

Please try

	git push --recurse-submodules=on-demand

or cd to the path and use

	git push

to push them to a remote.

如果你想要对所有推送都执行检查,那么可以通过设置 git config push.recurseSubmodules check 让它成为默认行为。

另一个选项是使用 "on-demand" 值,它会尝试为你这样做。

bash 复制代码
git push --recurse-submodules=on-demand

如你所见,Git 进入到 DbConnector 模块中然后在推送主项目前推送了它。 如果那个子模块因为某些原因推送失败,主项目也会推送失败。 你也可以通过设置 git config push.recurseSubmodules on-demand 让它成为默认行为。

4.4.2.合并子模块改动

如果你和其他人同时改动了一个子模块引用,那么可能会遇到一些问题。 也就是说,如果子模块的历史已经分叉并且在父项目中分别提交到了分叉的分支上,那么你需要做一些工作来修复它。

如果一个提交是另一个的直接祖先(一个快进式合并),那么 Git 会简单地选择之后的提交来合并,这样没什么问题。

不过,Git 甚至不会尝试去进行一次简单的合并。 如果子模块提交已经分叉且需要合并,那你会得到类似下面的信息:

bash 复制代码
git pull
remote: Counting objects: 2, done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 2 (delta 1), reused 2 (delta 1)
Unpacking objects: 100% (2/2), done.
From https://github.com/chaconinc/MainProject
   9a377d1..eb974f8  master     -> origin/master
Fetching submodule DbConnector
warning: Failed to merge submodule DbConnector (merge following commits not found)
Auto-merging DbConnector
CONFLICT (submodule): Merge conflict in DbConnector
Automatic merge failed; fix conflicts and then commit the result.

所以本质上 Git 在这里指出了子模块历史中的两个分支记录点已经分叉并且需要合并。 它将其解释为 "merge following commits not found" (未找到接下来需要合并的提交),虽然这有点令人困惑,不过之后我们会解释为什么是这样。

如果你运行 git diff,就会得到试图合并的两个分支中记录的提交的 SHA-1 值。

bash 复制代码
git diff
diff --cc DbConnector
index eb41d76,c771610..0000000
--- a/DbConnector
+++ b/DbConnector

所以,在本例中,eb41d76 是我们的子模块中大家共有 的提交,而 c771610 是上游拥有的提交。 如果我们进入子模块目录中,它应该已经在 eb41d76 上了,因为合并没有动过它。 如果不是的话,无论什么原因,你都可以简单地创建并检出一个指向它的分支。

来自另一边的提交的 SHA-1 值比较重要。 它是需要你来合并解决的。 你可以尝试直接通过 SHA-1 合并,也可以为它创建一个分支然后尝试合并。 我们建议后者,哪怕只是为了一个更漂亮的合并提交信息。

所以,我们将会进入子模块目录,基于 git diff 的第二个 SHA-1 创建一个分支然后手动合并。

bash 复制代码
$ cd DbConnector

$ git rev-parse HEAD
eb41d764bccf88be77aced643c13a7fa86714135

$ git branch try-merge c771610
(DbConnector) $ git merge try-merge
Auto-merging src/main.c
CONFLICT (content): Merge conflict in src/main.c
Recorded preimage for 'src/main.c'
Automatic merge failed; fix conflicts and then commit the result.

我们在这儿得到了一个真正的合并冲突,所以如果想要解决并提交它,那么只需简单地通过结果来更新主项目。

bash 复制代码
$ vim src/main.c (1)
$ git add src/main.c
$ git commit -am 'merged our changes'
Recorded resolution for 'src/main.c'.
[master 9fd905e] merged our changes

$ cd .. (2)
$ git diff (3)
diff --cc DbConnector
index eb41d76,c771610..0000000
--- a/DbConnector
+++ b/DbConnector
@@@ -1,1 -1,1 +1,1 @@@
- Subproject commit eb41d764bccf88be77aced643c13a7fa86714135
 -Subproject commit c77161012afbbe1f58b5053316ead08f4b7e6d1d
++Subproject commit 9fd905e5d7f45a0d4cbc43d1ee550f16a30e825a
$ git add DbConnector (4)

$ git commit -m "Merge Tom's Changes" (5)
[master 10d2c60] Merge Tom's Changes
  1. 首先解决冲突
  2. 然后返回到主项目目录中
  3. 再次检查 SHA-1 值
  4. 解决冲突的子模块记录
  5. 提交我们的合并

这可能会让你有点儿困惑,但它确实不难。

有趣的是,Git 还能处理另一种情况。 如果子模块目录中存在着这样一个合并提交,它的历史中包含了的两边的提交,那么 Git 会建议你将它作为一个可行的解决方案。 它看到有人在子模块项目的某一点上合并了包含这两次提交的分支,所以你可能想要那个。

4.5.子模块的技巧

4.5.1.子模块遍历

4.5.2.有用的别名

4.6.子模块的问题

4.6.1.切换分支

4.6.2.从子目录切换到子模块

4.7.子模块命令

bash 复制代码
absorbgitdirs
add             
deinit          
foreach         
init            
set-branch     
set-url         
status          
summary         
sync            
update  

附录A.托管服务器推荐

GitHub

全球大多数开源软件在这里安家,资源丰富,国外网站,速度有点慢。中国对这个网站很犹豫有时屏蔽,有时开放,需要科学上网才行。

开源中国git托管服务器

只对中国国内,速度快,资源不太丰富。

附录B.学习资料

git官网《Pro Git book》是一本很好的开源书籍。

廖雪峰git教程

git菜鸟教程

Windows本地手册

[Ubuntut本地手册](file:///usr/share/doc/git-doc)

本地手册使用浏览器打开,这里有大量网页帮助文档,太详细而显冗余。

相关推荐
和你一起去月球20 分钟前
TypeScript - 函数(下)
javascript·git·typescript
我不是程序猿儿1 小时前
【GIT】TortoiseGit的变基(Rebase)操作
git
yyycqupt8 小时前
git使用(一)
git
Kkooe11 小时前
GitLab|数据迁移
运维·服务器·git
Beekeeper&&P...12 小时前
git bash是什么,git是什么,git中的暂存区是什么,git中的本地仓库是什么,git中工作目录指的是什么
开发语言·git·bash
Stara051117 小时前
Git推送+拉去+uwsgi+Nginx服务器部署项目
git·python·mysql·nginx·gitee·github·uwsgi
lsswear17 小时前
GIT 操作
git
勋勋勋勋小勋勋17 小时前
git分支合并某一次提交
git
PandaCave18 小时前
git常用命令以及注意事项总结
git