git总结1

升级了git版本,git clone 的时候报了如下的错误

fatal: unable to access 'https://github.com/open-falcon/falcon-plus.git/': SSL connect error
百度了好久,试了好多方法,最后google到了解决方法,特记录下

解决方法: yum update -y nss curl libcurl

gerrit 上查找多个用户的提交
status:merged project:android/qiku/frameworks branch:QCOM_8976pro_7.x_360OS (owner:yangbinhu OR owner:zengzhigang OR owner:dengweihua OR owner:wangfuquan)

====================================================================================================
虚拟硬盘
MYDROID root 用户密码:zzg
ubuntu root 用户密码:123456

虚拟机安装配置gerrit过程
#####################################################
# [001] Install virtualbox and init virtual machine

1. Install VirtualBox
2. Double click MYDROID\MYDROID.vbox to start the VirtualMachine.!!

Recommand: free space of your VBox disk is larger than 300G

建议系统安装的一个虚拟机硬盘上,再创建一个虚拟机硬盘挂载到系统中用于存放数据。这样,当系统出问题重装中,另一个虚拟机硬盘中的数据不受影响

#####################################################
# [002] try to boot your vm

Both user & password of the VM: mine!!

NOTE: '/mnt/share/' is the share folder between VM and Windows host,
You should create F:\share on your Windows host or change the SHARE settings in your VBOX settings.


#####################################################
# [003] Add your own ssh pubkey

1> generate ssh key

$ ssh-keygen -t rsa
(accept all default values, just return...)


2> add all contents in '~/.ssh/id_rsa.pub' to your gerrit account (settings -> SSH Public Keys)
http://10.100.13.23:8080/#/settings/ssh-keys


3> !! important !!
$ ssh-add ~/.ssh/id_rsa


4> test ssh connection...
$ ssh -T -p 29418 your_account@10.100.13.23

if you see this message below, everything is ok, move on!

----------------------------------------------------------
**** Welcome to Gerrit Code Review ****

Hi XXXX, you have successfully connected over SSH.
----------------------------------------------------------

5> also you can try to pull git hook from server to test ssh connection.
$ scp -P 29418 -p your_account@10.100.13.23:/hooks/commit-msg .

#####################################################
# [004] Add following lines to the end of '~/.bashrc'
--------------------------------------------

alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'
alias ......='cd ../../../../..'

export PATH=~/bin:$PATH

--------------------------------------------
# Save, then run once :

$ source ~/.bashrc

#####################################################
# [005] Configure email & username

git config --global user.email "your_account@qiku.com"
git config --global user.name "your_account"


#####################################################
# [006] Init and sync the remote repo ... mkdir -p /media/extdisk/8992_6.x cd /media/extdisk/8992_6.x

$ repo init -u ssh://your_account@10.100.13.23:29418/android/qiku/manifests -b QCOM_8992_6.x_qiku
# wait to complete ...

$ repo sync
...


#####################################################
# [007] copy hooks
repo forall -c scp -P 29418 -p your_account@10.100.13.23:/hooks/commit-msg .git/hooks/


#####################################################
# [008] build


cd /media/extdisk/8992_6.x/android/qiku/

./build.sh QK8992 -u -v userdebug

or
:source build/envsetup.sh
lunch QK8692-userdebug


# then you can make any android project or module, e.g.
make framework showcommands


============================================================================================
Linux下载git2.2.1并将git添加到环境变量中

wget https://github.com/git/git/archive/v2.23-rc2.tar.gz
tar zxvf v2.23-rc2.tar.gz
cd git-2.2.1
make configure
./configure --prefix=/usr/local/git --with-iconv=/usr/local/libiconv
make all doc
make install install-doc install-html
echo "export PATH=$PATH:/usr/local/git/bin" >> /etc/bashrc
source /etc/bashrc

查看版本号
git --version
输出git --version 2.23-rc2

============================================================================================

git clone --recurse-submodules <main_project_url> # 获取主项目和所有子项目源码

git clone --recursive 用于循环克隆git子项目

使用 git clone 命令时出现了fatal: HTTP request failed报错。是由于git版本过低。
安装需求:

># yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel asciidoc
># yum install  gcc perl-ExtUtils-MakeMaker   

卸载Centos自带的git1.7.1:
通过git –version查看系统带的版本,Cento6.5应该自带的是git版本是1.7.1

># yum remove git
下载git2.23-rc2并将git添加到环境变量中

># wget https://github.com/git/git/archive/v2.23-rc2.tar.gz
># tar zxvf v2.23-rc2.tar.gz
># cd git-2.23-rc2
># make configure
># ./configure --prefix=/usr/local/git --with-iconv=/usr/local/libiconv
># make all doc
># make install install-doc install-html
or
make prefix=/usr/local/git all
make prefix=/usr/local/git install

># echo "export PATH=$PATH:/usr/local/git/bin" >> /etc/bashrc
># source /etc/bashrc


安装出现问题:
/bin/sh: line 1: xmlto: command not found
make[1]: *** [git-add.1] Error 127
make[1]: Leaving directory `/root/src/git/Documentation'
make: *** [doc] Error 2


安装xmlto
yum install xmlto

如果还报错,更新
yum update -y nss curl libcurl openssh


查看版本号
># git --version
>git version 2.23-rc2


============================================================================================
Git平台使用时的配置分析

Git仓库的配制文件分为三个部分:

1. .git/config:指定仓库配置(特定于某个仓库),获取或设置时使用--file参数(或者省去)。

2. ~/.gitconfig:用户级别仓库配置(适用用于特定用户下的所有仓库),获取或设置时使用--global参数。

3. /etc/gitconfig:系统级别仓库配置(适用于所有仓库),获取或设置时使用--system参数。

覆写关系为:小范围覆盖大范围属性;自上到下,作用范围越大。

在使用Git过程中,需要设置许多定制化的配置;比如:email、name、显示、输入等等。这些配置均写到上述文件中,且使用不同的指令会修改不同位置的文件,也就产生不同的范围。

下面分为不同的主题,讲述Git中涉及到的不同设置。

主题1:设置相关的系统属性、指令输入等配置

获取当前仓库的所有系统设置:
james@james-PC MINGW64 /d/GitDemo $ git config -l
core.symlinks=false
core.autocrlf=true
core.fscache=true
color.diff=auto<br>color.status=auto<br>color.branch=auto<br>color.interactive=true
help.format=html<br>http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt<br>diff.astextplain.textconv=astextplain<br>rebase.autosquash=true
credential.helper=manager<br>user.name=ZHANGEfeng-james<br>user.email=zfengwust3054@163.com<br>core.autocrlf=false

取消设置指令:
james@james-PC MINGW64 /d/GitDemo/public_html (master) $ git config --unset --global user.email <br>james@james-PC MINGW64 /d/GitDemo/public_html (master) $ git config -l
core.symlinks=false
core.autocrlf=true
core.fscache=true
color.diff=auto
color.status=auto
color.branch=auto
color.interactive=true
help.format=html
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
diff.astextplain.textconv=astextplain rebase.autosquash=true
credential.helper=manager
user.name=ZHANGEfeng-james
core.autocrlf=false
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.symlinks=false
core.ignorecase=true

设置指令别名:
james@james-PC MINGW64 /d/GitDemo/public_html (master) $ git config --global alias.st status <br>james@james-PC MINGW64 /d/GitDemo/public_html (master) $ git st

On branch master nothing to commit, working tree clean

james@james-PC MINGW64 /d/GitDemo/public_html (master) $ git config --global alias.ci commit <br>james@james-PC MINGW64 /d/GitDemo/public_html (master) $ git config --global alias.lg log
james@james-PC MINGW64 /d/GitDemo/public_html (master) $ git lg<br><br>commit 8bac1e803752ec07728a8a702043cfdae9370eac<br>Author: ZHANGEfeng-james <zfengwust3054@163.com><br>Date: Sat Dec 3 21:12:14 2016 +0800 <br> testOtherName to test<br>
commit 908c2e3a0bcc23486887700214f451b00afeb07b
Author: ZHANGEfeng-james <zfengwust3054@163.com>
Date: Sat Dec 3 21:02:13 2016 +0800
move test to testOtherName

上述设置结果,执行git lg等价于执行git log。

主题2:Git的忽略文件配置

Git版本控制中可通过配置.gitignore文件,将文件中的模式文件排除在Git管理之外。

.gitignore文件(一般会和.git目录在同一级)示例内容如下:

bin
gen
.classpath
.project
*.properties

若配置.gitignore文件为上述内容,Git将会排除下述情况:所有的bin、gen目录(包含本目录下的bin\gen,以及任何的子目录bin\gen等);后缀为classpath、project以及properties的文件。

.gitignore文件的配置语法如下:
1. 以斜杠“/”结尾,表示目录;
2. 以星号“*”,表示多个通配符;
3. 以问号“?”,表示单个通配符;
4. 以叹号“!”,表示不忽略(跟踪)匹配到的文件或目录;

此外,git对于.gitignore匹配文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面则不会生效。

举例:
1. fd1/*,说明:忽略fd1目录下的全部内容
2. /fd1/*,说明:忽略根目录下的/fd1/目录的全部内容;
3. bin:说明:忽略bin目录下的所有内容;不管是.../bin/目录下的内容还是/bin/目录下的内容都将被忽略

依照上述的忽略文件制作方式,可以制作同样的一份文件名为:.gitignore_global,其内容同上述。

并在包含.git/的工程中执行以下指令(如下指令确实需要执行,否则 Git 怎么知道使用忽略文件呢?):

git config --global core.excludesfile ~/.gitignore_global
也就是将全局忽略文件都设置为同一份:.gitignore_global;其中~/.gitignore_global为忽略文件所在路径。

查看全局配置文件 ~/.gitconfig
git config --global --list

git 还提供了另一种 exclude 的方式来做同样的事情,不同的是 .gitignore 这个文件本身会提交到版本库中去。用来保存的是公共的需要排除的文件。

而 .git/info/exclude 这里设置的 则是你自己本地需要排除的文件。 他不会影响到其他人。也不会提交到版本库中去。

============================================================================================

当本地commit一个提交和远端服务器中的代码有冲突(别人也改了相同的文件)时可以在pull 中加 –rebase。加上 rebase 的意思是:
git pull --rebase
1.把本地 repo. 从上次 pull 之后的变更暂存起來
2.恢复到上次 pull 时的状态
3.合并远端的变更到本地
4.最后再合并刚刚暂存下來的本地变更

不产生无用的merge的同步
有这么一种情况,用一个分支专门同步代码提供商的代码的时候,如果一般的pull会不断的产生一个merge看起来会很烦,用下边的使用添加一个--rebase就不会产生无用的merge了
$ git pull --rebase origin master

如果想要把 rebase 当做 git pull 的默认值,可以在 .git/config 加上
[branch "master"]
remote = origin
merge = refs/heads/master
rebase = true

也可以直接加到 ~/.gitconfig 让所有的 tracked branches 都自动套用这个设定:
[branch]
autosetuprebase = always


(浅克隆)

如果只拉取最近一次的变更,忽略以前的变更记录,在拉取时可以加参数depth,如git pull --depth=1 origin master

git merge --squash featureB

--squash 选项接受被合并的分支上的所有工作,并将其压缩至一个变更集,使仓库变成一个真正的合并发生的状态,而不会真的生成一个合并提交。
这意味着你的未来的提交将会只有一个父提交,并允许你引入另一个分支的所有改动, 然后在记录一个新提交前做更多的改动。
同样 --no-commit 选项在默认合并过程中可以用来延迟生成合并提交。

警告:运行git-merge时含有大量的未commit文件很容易让你陷入困境,这将使你在冲突中难以回退。
因此非常不鼓励在使用git-merge时工作目录中存在未commit的文件,建议使用git-stash命令将这些未commit文件暂存起来,并在解决冲突以后使用git stash pop把这些未commit文件还原出来。


冲突会产生三个文件:
local:指的本地要提交,要合并的状态。 窗口是“HEAD”

base:指的是local和remote共同的节点。

remote:指的是我们从服务器将上一次提交拉到本地对应的状态。 窗口是“要整合的更改”

合并后的文件。 窗口是“已合并”

<<<<< HEAD 和 ===== 标记是合并之前的本地文件之一。

==== 和>>>>> <分行名称> 是远程档案中的一个。

Git执行三向合并,找到要合并的两个分支的共同祖先(也称为“合并基础”)。因此:
foo.LOCAL:冲突的“我们的”一面 - 即包含合并结果的分支(HEAD)
foo.REMOTE:冲突的“他们”方面 - 你要合并的分支HEAD
foo.BASE:共同的祖先。对于提供三向合并工具很有用
foo.BACKUP:调用合并工具之前的文件内容将保留在mergetool.keepBackup = true的文件系统上。

============================================================================================
配置GIT提交的模板文件与编辑器

git config --global core.editor vim

git config --global commit.template /home/user/msm8994/commit.template // 这个命令设置全局的提交模板

git config commit.template [模板路径文件名] //这个命令只能设置当前分支的提交模板, 会改变当前目录.git中的config文件, windows上路径文件名类似于 c:/xxxx/commit.template

commit_template 内容暂定如下:
[Project]:MSM8994-17427
[Module]:
[ID]:
[Issue]:
[Solution]:
[Risk:]


提交需要拉取hook
scp -P 29418 -p yourname@10.100.13.26:/hooks/commit-msg .git/hooks/

============================================================================================
git常用配置
配置SSH主机明白
在.ssh目录创建config文件
内容格式为
host 主机命名
user 连接服务器的用户名
hostname 服务器ip地址或机器名
identityFile 密匙文件的具体路径

例如:
us@scm_fan:~$ cat .ssh/config
host gitSZ
user git
hostname 192.168.10.204
identityFile ~/.ssh/id_rsa.pub

1. git config --system /etc/gitconfig文件: 系统中对所有用户都普遍使用的配置
2. git config --global ~/.gitconfig文件: 用户目录下的配置文件只适用于该用户
3. 当前项目的git目录中的配置文件(工作区中的.git/config文件): 只针对当前项目有效。每个一个级别的配置都会覆盖上层的相同配置,所以.git/config的配置会覆盖/etc/gitconfig中的配置


用户信息的配置
user.name
user.email
文本编辑器 core.editor
差异分析工具merge.tool
配置显示方式 core.paper "less -N"
diff颜色配置 color.diff true
设置别名 alias.co checkout
git config --global alias.co checkout

查看配置信息
git config --list

直接查阅某个环境变量的设定
git config user.name

忽略修改权限的文件
git config core.filemode false

也可以通过编辑$GIT_DIR/info/exclude 文件将你需要忽略的文件写入其中与.gitignore文件的区别,就是这个你只能自己用, 不能通过提交.gitignore文件给整个项目组用。

通过git config --global core.excludesfile ~/.gitignore 对本机上的所有仓库进行忽略文件配置

忽略文件中的空格修改
git config --global apply.whitespace nowarn

7. 颜色配置
color.branch auto
color.diff auto
color.interactive auto
color.status auto
将颜色全部打开color.ui true
[color]
branch = auto
diff = auto
status = auto
[color "branch"]
current = yellow reverse
local = yellow
remote = green
[color "diff"]
meta = yellow bold
frag = magenta bold
old = red bold
new = green bold
[color "status"]
added = yellow
changed = green
untracked = cyan

8. 将默认的.git目录改为.test
修改shell 参赛 GIT_DIR=> export GIT_DIR=.test

忽略某些文件
通过创建名为.gitignore的文件,列出要忽略的文件模式,例如:
$cat .gitignore
*.[oa] #忽略所有以.o或.a结尾的文件
*~ #忽略所有以波浪符(~)结尾的文件
!lib.a #lib.a 除外
/TODO #仅仅忽略项目根目录下的TODO文件,不包括subdir/TODO
build/ #忽略build/目录下的所有文件
doc/*.txt #会忽略doc/note.txt 但不包括doc/server/arch.txt

git命令bieming
git config --global alias.co checkout

commit.template 提交说明模板
git config --global commit.template $HOME/.gitmessage.txt

core.pager 分页器,可以设置成more或者less(默认),甚至为空
git config --global core.pager '' 不管命令的输出量多少,都会在一页显示所有内容

user.signingkey 将GPG签署密匙设为配置项
设置密匙ID git config --global user.signingkey <gpg-key-id>
这样就不必每次运行git tag 命令时定义密匙
git tag -s <tag-name>

core.excludesfile定义无需纳入GIt管理的文件
创建一个内容和.gitignore类似的文件
git config --global core.excludesfile path-filename

help.autocorrect
该配置项在1.6及以上版本有效
命令补全和提示

color.ui Git会按照你需要自动为大部分的输出加上颜色
git config --global color.ui true
其他参数还有false和always false意味着不为输出着色,而always则表明在任何情况下都要着色

color.* 设置具体的命令
color.branch
color.diff
color.interactive
color.status
每个选项都有子选项,可以被用来覆盖其父设置。

core.autocrlf 处理行结束符
true 在提交时将CRLF转换为LF 签出代码时,LF会被转换成CRLF
input 在提交是将CRLF转换为LF 签出时不转换
false 取消此功能

core.whitespace 探测和修改空白问题,其4种抓选项中的2个默认被打开,另2个被关闭
默认被打开的2个选项是trailing-space和space-before-tab trailinig-space会查找每行结尾的空格, space-before-tab 会查找每行开头的制表符前的空格
默认被关闭的2个选项是indent-with-non-tab和cr-at-eol indent-with-non-tab会查找8个以上空格(非制表符)开头的行, cr-at-eol 让Git指定行尾回车符是合法的

git config branch.autosetupmerge true 自动从远程分支合并提交到本地分支,如果不做此设置你需要手动add track远程分支或手动merge 默认就是true

git config branch.autosetuprebase always 设置在pull是做rebase还是merge 可选的值有never 不自动rebase,local跟踪本地分支的分支进行rebase,remote 跟踪远程分支的进行rebase , always所有的跟踪分支都自动进行rebase


3.
有时候git clone下来后,文件的权限不对,需要chmod -R 777 .
但是这样git会发现很多的改变,事实上是不需要提交的。通过下面的配置可以让git忽略这种情况
git config core.filemode false 这条命令只能git库中执行


4. 配置优先级
git config -e 信息写在版本库中.git/config文件 针对单个版本库的配置信息
git config -e --global 信息写在用户主目录下的.gitconfig 针对当前用户的配置信息
git config -e --system 信息写在/etc/gitconfig 针对整个操作

优先级别依次降低

git配置文件使用的是INI文件格式。
git config命令可以读取和更改INI配置文件的内容。
git config <section>.<key>
git config <section>.<key> <value>
删除配置内容
$git config --unset --global user.name
$git config --unset --global user.email

5. remote 远程库信息配置
添加远程库 git remote add 远程库名称 地址
删除远程库 git remote rm 远程库名称
设置远程地址 git remote set-url 远程库名称 地址
git config --get remote.origin.url 获取远程库路径

通过git clone --bare 命令克隆的裸库是没有远程库的,需要手动添加,在添加了远程库之后git config --list 会多出如下两项
remote.origin.url=gitSZ:mt6573/platform/build.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*

可以手动编译git config remote.origin.fetch=+refs/*:refs/* 来匹配所有改动
remote.origin.mirror=true 作用不明?


6. 配置第三方图形化比较工具meld
A. 在/usr/local/bin 目录下创建extDiff 文件
cd /usr/local/bin
sudo gedit /usr/local/bin
内容为:
#!/bin/bash
/usr/bin/meld "$2" "$5"
这里的/usr/bin/meld可以替换成其他的工具
保存退出
B. 添加执行权限
sudo +x extDiff
C. 配置git
git config --global diff.external extDiff
配置完成
在执行git diff 的时候如果有多个文件,将会逐个显示,关闭掉当前文件窗口就会显示下一个文件。

上面多个文件比较时是足够显示的,下面设置类似于文件夹的比较
A. 从https://github.com/thenigan/git-diffall 下载脚本
可以将 git-diffall 放置在任意目录,添加可执行权限,我放在 /usr/local/bin
chmod o+x git-diffall
B. git config --global alias.diffall /usr/local/bin/git-diffall
C . git diffall tag1 tag2

配置完成

配置比较工具二
安装bcompare
下载.tar.gz 解压后执行install.sh 在[usr]输入/opt 按提示设置环境变量(64位ubuntu10.10测试成功,相同的方法12.04测试失败)
配置git
difftool
git config --global diff.tool bc3
git config --global difftool.bc3 trustExitCode

mergetool
git config --global merge.tool bc3
git config --global mergetool.diffmerge.cmd "cmld = bc3 --merge --result=$MERGED $LOCAL $BASE $REMOTE"

bcompare可以换成其他git支持的工具如果meld、kdiff3等等。

============================================================================================

关于stash

适用情况:做了修改后,还没有add commit等等后续工作,现在突然要切换分支做其它事情,默认情况下你在这个分支修改的代码会被带到切换过去的分支中。
可以先把你修改的保存起来。这些修改可以再还原过来。

$ git stash -u // -u是代表是也把添加的新文件(术语是未跟踪)也藏起来,一般是要有这个u的。
$ xxxx 随便你的操作
$ git stash pop

两种恢复现场方式:
git stash apply 恢复后,stash 内容并不删除,你需要用git stash drop 来删除;执行一次就删除 stash@{0} 的缓存
git stash pop 恢复的同时把stash 内容也删了:

注意:如果stash pop 时有冲突而中断,则需要解决冲突后,再次 stash pop 才能继续恢复现场,恢复成功后,stash内容会被清除

你可以多次stash,恢复的时候,先用git stash list 查看,然后恢复指定的stash,用命令:$ git stash apply stash@{0}

如果一个COMMIT你不想要了,想要去除,可以考虑使用以下的方法;
$ git revert xxxx // 这个就可以去掉这个COMMIT的改动,这个是明式的去掉(本地工作区会变成恢复的内容),如果你又后悔了,还可以再次恢复。


Git打包源码
对Git管理的源码进行压缩打包,如果使用tar xvzf xxxx.tag.gz xxxxx的话并不是一个很好的选择,因为会将.git/目录下的中间文件全部压缩,
如果只想要某一个版本的源码。Git提供了archive.它会给打包一份纯净的代码。当然这个只适用于发部一个版本的源码,而不是备份Git管理的整套源码。

$ git archive xxxx // xxx代表SHA-1 Hash值。

============================================================================================

Git打包解包

免不了要做这些事情,直接将项目所在目录打包是最直观的,但是对于超级大的项目来说会很占空间。
而事实上只需要.git目录就可以将所有源码进行还原,以下是打包解包过程。

打包:
tar cvzf xxx.tar.gz .git

解包:
tar xvf xxx.tar.gz
mv xxx .git
git fsck --full #该命令的作用是从.git还原为最新源码


仓库中的脚本赋予执行权限
git update-index --chmod=+x script.sh
commit 并 push 后,问题就解决了

查看文件权限信息
$ git ls-files --stage
100644 eeac3244a04c3a7883093e904812355ced28fe81 0 cmake_build.sh

发现644(r=4,w=2,x=1),需要将其修改为可执行权限755

git ls-files [-z] [-t] [-v] [-f]
(--[cached|deleted|others|ignored|stage|unmerged|killed|modified])*
(-[c|d|o|i|s|u|k|m])*
[--eol]
[-x <pattern>|--exclude=<pattern>]
[-X <file>|--exclude-from=<file>]
[--exclude-per-directory=<file>]
[--exclude-standard]
[--error-unmatch] [--with-tree=<tree-ish>]
[--full-name] [--recurse-submodules]
[--abbrev] [--] [<file>…​]

输出格式 [<tag> ]<mode> <object> <stage> <file>

$ git ls-files --stage cmake_build.sh
100644 eeac3244a04c3a7883093e904812355ced28fe81 0 cmake_build.sh

增加可执行权限
git update-index --chmod +x cmake_build.sh

============================================================================================

git查看远程仓库地址

git remote 列出所有远程主机
orgin


git remote 列出所有远程主机
caf

git remote -v 查看远程主机地址

bruce@wfserver10:~/qcom/msm8994_dev/packages/apps/PackageInstaller$ git remote -v
caf git://192.168.19.26/m8994_05110/msm8994/packages/apps/PackageInstaller (fetch)
caf git://192.168.19.26/m8994_05110/msm8994/packages/apps/PackageInstaller (push)

git remote show <主机名> 显示远程主机详细信息

git remote add <主机名> <网址> 添加远程主机
git remote rm <主机名> 删除远程主机
git remote rename <原主机名> <新主机名> 远程主机的改名

bruce@wfserver10:~/qcom/msm8994_dev/packages/apps/PackageInstaller$ git remote show caf
* remote caf
Fetch URL: git://192.168.19.26/m8994_05110/msm8994/packages/apps/PackageInstaller
Push URL: git://192.168.19.26/m8994_05110/msm8994/packages/apps/PackageInstaller
HEAD branch (remote HEAD is ambiguous, may be one of the following):
development
master
release
rom_development
stable
Remote branches:
development tracked
master tracked
release tracked
rom_development tracked
stable tracked
Local branch configured for 'git pull':
development merges with remote rom_development
Local ref configured for 'git push':
development pushes to development (up to date)
bruce@wfserver10:~/qcom/msm8994_dev/packages/apps/PackageInstaller$

============================================================================================
git常见问题操作

1. 通过repo下载下来的代码默认git服务器是不能通过git push origin HEAD:refs/for/rom_development
可以配置服务器 git remote add origin ssh://xxx:192.168... (把ssh://开头的内容替换成git clone后面的地址)
git remote add 远端仓库名 对应的url

2. 每次提交都要输入git push origin HEAD:refs/for/rom_development,输入很麻烦,可以这样配置:
git config --global alias.pushg "push origin HEAD:refs/for/rom_development"
然后提交的时候只需要输入git pushg

3. git从一个仓库更新,提交到另一个仓库?
从git clone https://github.com/a/a.git 更新。 a是别人的代码仓库,提交到代码仓库 https://github.com/b/b.git 请问应该怎么做?

[解决办法]
git push https://github.com/b/b.git mybranch:remote_branch_name
git push 远程仓库地址 本地分支名:远程分支名

Git克隆某一个特定的远程分支
git clone -b <branch name> [remote-repository-addres]

git clone xxx.git "指定目录"

4.在本地仓库添加一个远程仓库,并将本地的master分支跟踪到远程分支

$ git remote add origin junmuzi@202.201.12.221:/git/test_git/.git 在本地仓库添加一个远程仓库,当然ssh后面的地址是我们本地仓库的地址.

$ git push origin master 将本地master分支跟踪到远程分支,在git仓库建立之初就会有一个默认的master分支,当然你如果建立了其他分支,也可以用同样的方法去跟踪.


git remote add origin 你的远程库地址 // 把本地库与远程库关联

git push -u origin master // 第一次推送时

git push origin master // 第一次推送后,直接使用该命令即可推送修改

git push命令,实际上是把当前分支master推送到远程。执行此命令后会要求输入用户名、密码,验证通过后即开始上传。
说明:用户名密码需要通过命令 ssh-keygen -t rsa -C “xxxxxx@qq.com” 进行创建,并且要把得到的秘钥(公钥)文件放到git服务器上,这样才有权限进行代码推送

5,我觉得现在重要的就是设置git push, pull默认的提交获取分支,这样就很方便的使用git push 提交信息或git pull获取信息

$ git branch --set-upstream-to=origin/dev localbranch //其中origin/dev是远程仓库的分支;而localbranch是自己的本地分支, 命令影响的是config文件

$ git branch --unset-upstream master 取消对master的跟踪

$ git branch -a 能看到当前repository里面所有的分支

$ git branch -r 显示所有远端分支。

$ git branch -vv(两个v),就能够看到本地分支跟踪的远程分支。 (旧版本上的用法)

$ git config --list 查看远端跟踪分支
user.email=yangbinhu@qiku.com
user.name=yangbinhu
color.ui=auto
core.repositoryformatversion=0
core.filemode=true
remote.origin.url=ssh://wangfuquan1@10.100.13.23:29418/android/qiku/frameworks
remote.origin.projectname=android/qiku/frameworks
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.QCOM_8992_6.x_qiku.remote=origin
branch.QCOM_8992_6.x_qiku.merge=QCOM_8992_6.x_qiku

比如下面的结果说明本地 master 分支 track 的是 origin 库的 master 分支。
$ git config -l | grep 'branch\.master'
branch.master.remote=origin
branch.master.merge=refs/heads/master

6.取消上次的提交

git revert 是撤销某次操作,此次操作之前的commit都会被保留,指定commit-id及其之后的提交都将被撤消

git reset <file> 是撤销某次提交,但是此次之后的修改都会被退回到暂存区

根据–-soft –-mixed -–hard,会对working tree和 index 和 HEAD进行重置:

git reset –-mixed commit_id:此为默认方式,不带任何参数的git reset,即时这种方式,它回退到某个版本,只保留源码,回退commit和index信息

git reset –-soft commit_id: 回退到某个版本,只回退了commit的信息,不会恢复到index file一级。如果还要提交,直接commit即可

git reset –-hard commit_id: 彻底回退到某个版本,本地的源码也会变为上一个版本的内容


HEAD 最近一个提交
HEAD^ 上一次(类推..)
<commit_id> 每次commit的SHA1值. 可以用git log 看到,也可以在页面上commit标签页里找到


git reset --hard 回滚到之前的版本以后,怎么撤销这一步回滚操作?

可以通过reflog来进行恢复,前提是丢失的分支或commit信息没有被git gc清除, 一般情况下,gc对那些无用的object会保留很长时间后才清除的

可以使用git reflog show 或 git log -g 命令来看到所有的操作日志

git的历史记录,你可以看到两次提交:
$ git log
* 98abc5a (HEAD, master) more stuff added to foo
* b7057a9 initial commit

现在让我们来重置回第一次提交的状态:
$ git reset --hard b7057a9
$ git log
* b7057a9 (HEAD, master) initial commit

这看起来我们是丢掉了我们第二次的提交,没有办法找回来了。但是 reflog 就是用来解决这个问题的。简单的说,它会记录所有HEAD的历史,也就是说当你做 reset,checkout等操作的时候,这些操作会被记录在reflog中。

$ git reflog
b7057a9 HEAD@{0}: reset: moving to b7057a9
98abc5a HEAD@{1}: commit: more stuff added to foo
b7057a9 HEAD@{2}: commit (initial): initial commit

所以,我们要找回我们第二commit,只需要做如下操作:
$ git reset --hard 98abc5a

再来看一下 git 记录:
$ git log
* 98abc5a (HEAD, master) more stuff added to foo
* b7057a9 initial commit

所以,如果你因为reset等操作丢失一个提交的时候,你总是可以把它找回来。除非你的操作已经被git当做垃圾处理掉了,一般是30天以后。


git revert 也是撤销命令,区别在于 git reset 是指向原地或者向前移动指针,git revert是创建一个commit来覆盖当前的commit,指针向后移动

git revert --continue 用这个命令生成新的提交,完成最终确认


7. 查看LOG
我们常用 -p 选项展开显示每次提交的内容差异,用 -2 则仅显示最近的两次更新:

$ git log -p -2

--stat,仅简要的显示 文件 增改行数统计,每个提交都列出了修改过的文件,以及其中添加和移除的行数,并在最后列出所有增减行数小计。

$ git log --stat

--author 仅显示指定作者相关的提交。

$ git log --author=haiwang 查找 haiwang 提交的版本;

--graph 图示提交过程

$ git log --graph

$ git log --graph --oneline --decorate 一起用更容易查看哪个提交属于哪个分支

-oneline- 压缩模式,在每个提交的旁边显示经过精简的提交哈希码和提交信息,以一行显示。

8. 创建新的分支并绑定远端分支

git checkout -b <branchname> <start_point>

$ git checkout -b development remotes/origin/rom_development 创建并切换到新分支 development 与远端分支 rom_development 建立跟踪关系,

9. 更改远程仓库名称对应的地址
git remote set-url <name> <newurl>

git remote set-url origin ssh://bruce.zeng@192.168.19.26:29418/m8994_05110/external/sepolicy

10. 更改本地分支对应的远端分支

git branch --set-upstream origin/rom_development 修改当前分支所对应的远端分支为 rom_development(--set-upstream 已过时,被 --set-upstream-to 取代)

11. 暂存与恢复本地修改

$ git stash xxxx.file

刚才的工作现场存到哪去了?用git stash list 命令看

需要恢复,有两个办法:
$ git stash apply 恢复,但是恢复后,stash 内容并不删除,你需要用git stash drop 来删除;
$ git stash pop,恢复的同时把stash 内容也删了

可以多次stash,恢复的时候,先用git stash list 查看,然后恢复指定的stash,用命令:
$ git stash apply stash@{0}

12. 比较文件

比较当前文件和某一历史记录:

git diff <commit hash> 文件名

13. 取回旧版本

git reset <commit hash> 文件名

git checkout <commit-id> -- 文件名

git reset HEAD <file> 取消指定文件在index中的缓存

14. 从分支中提取指定文件

git checkout [branch] -- [file name]

15. 对上次的提交进行修订

git commit --amend

注意:如果提交前在仓库的 .git/hooks目录下没有gerrit的钩子,则 git log 中不会显示 "Change-Id:xxxxx...", 这时需要在有了钩子后,再次执行这个命令来产生ID。

提交指定文件: git commit [file]

16. 提交发生冲突的处理

git pull --rebase <origin> <master>

当本地commit一个提交和远端服务器中的代码有冲突(别人也改了相同的文件)时可以在pull 中加 –rebase。加上 rebase 的意思是:
1.把本地 repo. 从上次 pull 之后的变更暂存起來
2.恢复到上次 pull 时的状态
3.合并远端的变更到本地
4.最后再合并刚刚暂存下來的本地变更

rebase vs. merge

rebase 跟 merge 类似,出现 conflict 会暂停 rebase 动作,需要你手动修复后,然后才可以继续动作。
这也是 rebase 比 merge 复杂一点的地方:merge 如果发生 conflict,你只需要解决冲突一次,然后commit 出去就完成了。

而 rebase 的 conflict 可能会发生在上述步骤 4 的每一次重新套用上,所以可能需要解决冲突好几次 (rebase 时所谓的解决冲突,其实是直接修改你之前的变更內容 )。

git pull 获取并合并其他的仓库,或者本地的其他分支。 git pull 与 git push操作的目的相同,但是操作的目标相反。命令格式如下:

git pull <远程主机> <远程分支>:<本地分支>

例如: git pull origin master:my_test

上面的命令是将origin仓库的master分支拉取并合并到本地的my_test分支上。如果省略本地分支,则将自动合并到当前所在分支上。如下:git pull origin master


17. git rebase 使用

如果你想让"mywork"分支历史看起来像没有经过任何合并一样,你也许可以用 git rebase:

$ git checkout mywork
$ git rebase origin

这些命令会把你的"mywork"分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到".git/rebase"目录中),
然后把"mywork"分支更新 为最新的"origin"分支,最后把保存的这些补丁应用到"mywork"分支上。

解决冲突:
在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决 冲突;
在解决完冲突后,用"git-add"命令去更新这些内容的索引(index), 然后,你无需执行 git-commit,只要执行:
$ git rebase --continue

这样git会继续应用(apply)余下的补丁。

在任何时候,你可以用--abort参数来终止rebase的行动,并且"mywork" 分支会回到rebase开始前的状态。

$ git rebase --abort

18.使用Git Grep进行搜索

git grep <-n> xxx

用git grep 命令查找Git库里面的某段文字是很方便的. 当然, 你也可以用unix下的'grep'命令进行搜索,
但是'git grep'命令能让你不用签出(checkout)历史文件, 就能查找它们.
如果你要显示行号, 你可以添加'-n'选项; 如果我们想只显示文件名, 我们可以使用'--name-onley'选项;
我们用'-c'选项,可以查看每个文件里有多少行匹配内容

如果我们要查找git仓库里某个特定版本里的内容, 我们可以像下面一样在命令行末尾加上标签名

git grep xmmap v1.5.0

我们也可以组合一些搜索条件, 下面的命令就是查找我们在仓库的哪个地方定义了'SORT_DIRENT'.

$ git grep -e '#define' --and -e SORT_DIRENT

builtin-fsck.c:#define SORT_DIRENT 0
builtin-fsck.c:#define SORT_DIRENT 1

19. 提交后,审核不过的处理

你的提交推送gerrit,会有一个 "Change-ID"。如果该提交有问题,按下面步骤执行;
a. git pull --rebase 把服务器仓库最新代码拉到本地,并与本地代码整合
b. 解决问题(冲突,修订。。。)
c. 重新提交 git commit --amend , 修改note,wq存盘退出
d. git push origin HEAD:refs/for/rom_development 再次推送,这时针对该笔提交,gerrit会产生一个PATCH,审核者针对最后的PATCH进行审核入库即可。
如果提示出错,使用 git push --no-thin origin HEAD:refs/for/rom_development

你提交了错误的分支,Aandoned后,想要推送到正确的分支,按下面步骤执行:
a. git commit --amend 删掉 "Change-ID: xxxx" 这行
b. git push HEAD:xxx 最近的提交内容推送到正确的分支xxx
c. git push :xxx 删除远程的分支xxx

20. 移除所有未跟踪文件

git clean [options] 一般会加上参数-df (-d表示包含目录,-f表示强制清除)。

对git未跟踪的文件不跟踪: 将该文件加入.gitignore文件即可

停止对git已跟踪的文件跟踪,但保留之前该文件的跟踪状态: git rm --cached 文件名

暂时让git忽略已跟踪的文件: git update-index --assume-unchanged 文件名

21. 交互式暂存

使用git add -i可以开启交互式暂存,系统会列出一个功能菜单让选择将要执行的操作。

22. git fetch 和 git pull 的区别

git fetch 和 git pull都可以用来更新本地库,它们之间有什么区别呢

git fetch 只会将本地库所关联的远程库的commit id更新至最新。只同步与远程分支关联的本地分支

git pull会将本地库更新至远程库的最新状态(是git fetch; git merge 的组合效果), 会同步所有远程分支

23. 合并分支

$ git merge dev // 将dev分支合并到当前分支

Updating d17efd8..fec145a

Fast-forward // Fast-forward 表示是合并方式是“快进模式”,也就是指针移动

readme.txt | 1 +

1 file changed, 1 insertion(+)

$ git branch -d dev // 合并完可以删除dev分支了

通常,合并分支时,如果可能,Git 会用“Fast forward”模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用“Fast forward”模式,Git 就会在merge 时生成一个新的commit,这样,从分支历史上就可以看出分支

准备合并dev 分支,请注意--no-ff 参数,表示禁用“Fast forward”:

$ git merge --no-ff -m "merge with no-ff" dev

Merge made by the 'recursive' strategy.

readme.txt | 1 +

1 file changed, 1 insertion(+)

因为本次合并要创建一个新的commit,所以加上-m 参数,把commit 描述写进去。
合并后,我们用git log 看看分支历史:
$ git log --graph --pretty=oneline --abbrev-commit
* 7825a50 merge with no-ff
|\
| * 6224937 add merge
|/
* 59bc1cb conflict fixed
...

可以看到,不使用“Fast forward”模式,merge 后就像上面这样。

合并分支时,加上--no-ff 参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward 合并就看不出来曾经做过合并。

合并另一个分支到当前分支后,推送到服务时,加上 --no-thin 参数
git push --no-thin origin HEAD:refs/for/cts


git push 远程仓库名
1. $ git push ssh://git@dev.lemote.com/rt4ls.git master //把本地仓库提交到远程仓库的master分支中

2. $ git remote add origin ssh://git@dev.lemote.com/rt4ls.git // 定义 origin 指代远程仓库url
$ git push origin master

这1,2操作是等价的,第二个操作的第一行的意思是添加一个标记,让origin指向ssh://git@dev.lemote.com/rt4ls.git,也就是说你操作origin的时候,实际上就是在操作ssh://git@dev.lemote.com/rt4ls.git。origin理解为一个别名。
注意:需要说明的是,默认情况下, 这条语句等价于提交本地的master分支到远程仓库,并作为远程的master分支。

如果想把本地的某个分支test 提交到远程仓库,并作为远程仓库的master分支,或者作为另外一个名叫test的分支,那么可以这么做。
$ git push origin test:master // 提交本地test分支作为远程的master分支

$ git push origin test:test // 提交本地test分支作为远程的test分支

git push origin [本地分支]:[远端分支]

如果想删除远程的分支呢?类似于上面,如果:左边的分支为空,那么将删除:右边的远程的分支。
$ git push origin :test // 刚提交到远程的test将被删除,但是本地还会保存的,不用担心。

23. 推送到其他分支
git checkout others_branch
git cherry-pick <commit id> // 将commit-id所在分支上的修改合并到当前分支

24. 进行可视化编辑
git citool

25. 进行图形化提交纪录查看界面
gitk // 上半个窗口显示的是历次提交的分支祖先图,下半个窗口显示当前点选的提交对应的具体差异

26. 检查仓库大小
$ git count-objects -v
count: 0
size: 0
in-pack: 207332
packs: 1
size-pack: 1305214
prune-packable: 0
garbage: 0
size-garbage: 0

查看 Git 仓库占用空间
$ du -hs .git/objects
45M .git/objects

27. git仓库廋身
$ git gc --prune

Git 垃圾回收
git gc --auto

28. 对一笔提交生成patch文件
$ git format-patch -l <commit id> xxxx.patch

检验patch:
git fetch origin sp_sc7731c_6.x_bir // 获取远端指定分支内
git checkout remotes/origin/sp_sc7731c_6.x_bir -b sp_sc7731c_6.x_bir //基于远端分支,创建本地分支
git patch -p1 < xxx.patch // 合入patch,看有没有冲突


29. 取得git 打好的tag所对应的代码

先 git clone 整个仓库,然后 git checkout tag_name 就可以取得 tag 对应的代码了。
但是这时候 git 可能会提示你当前处于一个“detached HEAD" 状态,因为 tag 相当于是一个快照,是不能更改它的代码的,
如果要在 tag 代码的基础上做修改,你需要一个分支:git checkout -b branch_name tag_name
这样会从 tag 创建一个分支,然后就和普通的 git 操作一样了。


30. 修改文件权限属性 755 -> 664

git diff HEAD^ --name-only | while read f; do if [ -f $f ]; then if ls -l $f | grep "rwx" >/dev/null; then chmod 664 $f; fi; fi; done

31. 复制代码仓库

git clone --bare /var/www/html/myrepo.git . // 没有指定目录时,默认会在当前目录下创建一个目录

用法1:git clone <repository> <directory>
将<repository>指向的版本库创建一个克隆到<directory>目录。目录<directory>相当于克隆版本库的工作区,文件都会检出,版本库位于工作区的.git目录中

用法2:git clone --bare <repository> <directory.git>

用法3:git clone --mirror <repository> <directory.git>

用法2和用法3创建的克隆版本库都不包含工作区,直接就是版本库的内容,这样的版本库称为裸版本库。

一般约定俗成裸版本库的目录名以.git做后缀,所以上面示例中将克隆出来的裸版本库目录名写作<directory.git>。

区别在于用法3克隆出来的裸版本对上游版本库进行了注册,这样可以在裸版本库中使用git fetch命令和上游版本库进行持续同步。

不使用--bare或--mirror创建出来的克隆包含工作区,这样就会产生两个包含工作区的版本库,这两个版本库对等。
这两个工作区本质上没有区别,往往提交在一个版本A中进行,另一个B作为备份。
只能从B执行git pull命令从A中拉回新的提交实现版本库同步,而不能从版本库A向版本库B执行git push推送操作, 还可以通过git init的方式创建裸版本库,需要加--bare参数。
当执行git push命令时,如果没有设定推送的分支,而且当前分支也没有注册到远程的某个分支,将检查远程分支是否有和本地相同的分支名(如master),如果有,则推送,否则报错。

32. 打包时候嵌入版本号

git rev-parse HEAD > version.txt

33. 备份所有修改过的文件

// git for windows 下将当前工作区修改过的文件打包
$ git diff --name-only | xargs tar -czvf update.tar.gz

// linux下将608e120 到 4abe32e 改动过的文件打包
git diff 608e120 4abe32e --name-only | xargs zip update.zip

git diff --name-only HEAD commit_id | xargs tar -zcvf diff_head.tar.gz

// linux下将当前工作区修改过的文件打包
git diff --name-only | xargs zip update.zip

// 复制差异文件,--parents 保留路径关系
git diff eb7ba86 580031 --name-only | xargs -I{} cp --parents {} ../patch/

34. 恢复所有修改

git status | grep modified | cut -d : -f 2 | xargs -i git checkout {}

35. 生成patch和合入patch
1. 在当前的工作目录下生成diff.patch文件。
git diff > diff.patch

2. 合入当前目录下的diff.patch文件
git apply diff.patch

3. 你可以用git apply --check 查看补丁是否能够干净顺利地应用到当前分支中


36. switch

我们注意到切换分支使用git checkout <branch>,而前面讲过的撤销修改则是git checkout -- <file>,同一个命令,有两种作用,确实有些让人迷惑。

实际上,切换分支的这个动作,用switch更加科学。因此最新的git版本提供git switch命令来切换分支:

$ git switch -c dev
直接切换到已有的master分支,可以使用:

$ git switch master
使用新的git switch命令,比git checkout要更容易理解。

Git鼓励大量使用分支:
查看分支  git branch
创建分支  git branch <name>
切换分支  git checkout <name> or git switch <name>
创建+切换分支  git checkout -b <name> or git switch -c <name>
合并某分支到当前分支  git merge <name>
删除分支  git branch -d <name>

============================================================================================
.git/config git库中config文件内容

[remote "origin"]
url = ssh://bruce.zeng@192.168.19.26:29418/m8994_05110/external/sepolicy
fetch = +refs/heads/*:refs/remotes/origin/*

origin是一个远程仓库的别名,它实际指向 url
fetch = +refs/heads/*:refs/remotes/origin/*, 意味着会将远端仓库中所有位于refs/heads目录下的分支下载到本地的refs/remotes/origin目录下面
远端 : 本地

[branch "development"]
remote = origin 意味着当前分支"development"会从origin远端仓库提取分支。
merge = refs/heads/development 意味着git会将远端仓库中refs/heads目录下的 development 分支与当前分支合并
rebase = true


.gitconfig 内容

[alias]
pushg = push origin HEAD:refs/for/rom_development
pushcta = push origin HEAD:refs/for/cta_development
pushcts = push origin HEAD:refs/for/cts
pushrel = push origin HEAD:refs/for/release
pushdev = push origin HEAD:refs/for/development
============================================================================================
在一系列历史提交中修改一个特定的commit并push

git使用amend选项提供了最后一次commit的反悔。但是对于历史提交呢,就必须使用rebase了。

如何修改你已经commit的一个历史提交?
比如:
HEAD
commit3
commit2
commit1(需要修改这个提交)
commit0(db7661ce4cb459da594a947977d0a86d14d40693)

我上网查找并结合自己实际检验,方法如下:
1.先Git rebase到要修改的commit之前那个commit
git rebase --interactive 'db7661ce4cb459da594a947977d0a86d14d40693'

2.在默认的编辑器中,把你想修改的commit的标签从pick修改成edit。然后做如下操作
git commit --all --amend --no-edit

3.git log检查当前的commit是不是你要修改的commit
修改你的提交,并修改这个commit
我事先有把相关修改使用git stash隐藏起来,这样我就可以用git stash pop 恢复我的修改
然后
git status
git add *
git commit --amend

修改特定的提交。

git rebase --continue
git log
git rebase --continue
git log

如果有必要再推送指定commitid到指定的提交上。
git push origin 0d163929c2407b00a8c16b745b520d07b854c207:refs/changes/857344


要重新修改1个commit的方法如下:
1. git rebase -i <targetCommit>~3 : 回到提交点的最后3次,用edit来表示需要更改
回车之后就进入了类似界面: 每一行pick代表了每一次commit记录,这个时候修改其中一个pick为e或edit,按ctrl+x退出,提示保存,输入y保存回车.
pick:*******
pick:*******
pick:*******

2. git reset --mixed HEAD~1 : 将这个targetCommit的改动放回working directory, object store 和 index都还原成这个commit尚未放入的状态
重新commit

2. git commit --amend 回车打开需要修改了当前commit,进行修改后,安装1的保存方法保存退出.

3. git rebase --continue 回车执行修改的生效,如果第一步编辑了多个pick记录的话,接下来会提示你继续使用2命令,然后重复执行2,3,最后都修改完了的话,会提示成功.

 

git中将当前改动追加到历史提交上可以使用命令git commit --amend实现, 下面介绍的两种解决方案都使用了这样命令)
<一> 下面是直接更改某次提交的操作步骤:
将HEAD移到需要更改的commit上:
git rebase f744c32cf74454a74bb2f80e5e38b120cb475af1^ --interactive
找到需要更改的commit, 将行首的pick改成edit, 按esc, 输入:wq退出
更改文件
使用git add 改动的文件添加改动文件到暂存
使用git commit --amend追加改动到第一步中指定的commit上
使用git rebase --continue移动HEAD到最新的commit处
这里会有冲突, 需要解决:
编辑冲突文件, 解决冲突
git add .
git commit --amend
解决冲突之后再执行git rebase --continue

上述方法, 是改动某个指定的commit, 如果我要将工作空间中已经改动的东西追加到某个commit上, 那么改如何做呢?

<二>将工作空间中的改动追加到某次提交上的步骤如下:
保存工作空间中的改动git stash
后面的步骤就和上面的决绝方案的步骤差不多, 只是第2步的更改文件改成执行命令git stash pop, 其他步骤都一样
这样处理之后, 如果branchB分支需要branchA分支上的某个功能, 只需要找到这个功能的惟一的一个提交记录即可, 就不需要在很多commit之中寻找这个功能点的相关提交记录.
更改合并之后再移动功能点, 就简单了许多, 执行找到功能点的惟一一个提交记录, 让后使用git cherry-pick commit-hash即可, 操作示意图如下:

功能点的提交合并到一个commit之后, 移动功能点的操作示意图
总结: 上述更改摸个提交记录/将现有改动追加到某个commit之上的方案在实际开发环境中的需求并不多, 而且实现起来有相当的局限性, 原因如下:

如果版本规划比较清晰, 就不会出现某个功能在不同版本之间穿梭的情形, 出现这种情况的大部分原因是: 多个版本的开发并发进行
实际开发中一次提交中的改动不可能只改动一个功能点 (如果模块或者功能点的边界划分的十分清晰, 是可以做到每次只改动一个功能点的)


分支和改基
不时地进行基础调整比上述两个示例要复杂一些。 在这种情况下,最重要的是避免破坏历史。 因此,作为预防措施,应首先在插入点创建一个分支:

git checkout C
git branch insert
这给出了以下内容:

A---B---C---D---E
^ ^
insert master
HEAD
现在,可以添加一个额外的提交(或多个):

touch insert.txt
git add insert.txt
git commit -m"Commit file insert.txt"
这是结果树:

A---B---C---D---E
\ ^
\ master
\
N
^
insert
最后,让我们将master分支移到包含新插入的提交的insert分支的顶部。 它需要使用rebase命令的另一个选项,即--onto :这允许从提交点“ --onto ”一部分Git树,然后将其“ --onto ”到另一个提交之上。

git checkout master
git rebase--onto insert C (1)
获取当前分支( master )和C之间的提交,并将其移到insert顶部
这是结果树:

A---B---C
\
\
\
N---D---E
^ ^
insert master
或以另一种方式看待它:

A---B---C---N---D---E
^ ^
insert master
理想情况下,现在insert分支应该被删除,尽管并非绝对必要:git branch -d insert

============================================================================================
GIT 排除/忽略文件或目录


由于git不会加入空目录,所以下面做法会导致tmp不会存在 tmp/* 忽略tmp文件夹所有文件
改下方法,在tmp下也加一个.gitignore,内容为
*
!.gitignore

还有一种情况,就是已经commit了,再加入gitignore是无效的,所以需要删除下缓存

git rm -r --cached ignore_file

注意:

.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。

正确的做法是在每个clone下来的仓库中手动设置不要检查特定文件的更改情况。

git update-index --assume-unchanged PATH 在PATH处输入要忽略的文件。

另外 git 还提供了另一种 exclude 的方式来做同样的事情,不同的是 .gitignore 这个文件本身会提交到版本库中去。用来保存的是公共的需要排除的文件。

而 .git/info/exclude 这里设置的则是你自己本地需要排除的文件。 他不会影响到其他人,也不会提交到版本库中去。

.gitignore 还有个有意思的小功能, 一个空的 .gitignore 文件 可以当作是一个 placeholder 。当你需要为项目创建一个空的 log 目录时, 这就变的很有用。

你可以创建一个 log 目录 在里面放置一个空的 .gitignore 文件。这样当你 clone 这个 repo 的时候 git 会自动的创建好一个空的 log 目录了。


一. 取消追踪某个文件

git update-index -–assume-unchanged file_path

- file_path 绝对路径

执行取消追踪命令, 带来效果:
1. 本地的当前分支取消了追踪
2. 本文文件不删除, 远程仓库仍是存在此文件。
3. 本次clone的所有分支都不追踪此文件。
4. 重新git clone后此文件仍是会被追踪。
5. 若想彻底取消并删除追踪文件
git rm file_path

二. 重新跟踪某个文件

git update-index –-no-assume-unchanged file_path

- file_path绝对路径

============================================================================================
Git忽略规则

注意忽略只对未跟踪文件有效,对于已加入版本库的文件无效。

一、三级忽略文件

1. 版本库共享式忽略文件

版本库中目录下的.gitignore文件作用于整个目录及子目录,会随着该版本库同其他人共享。

2. 本地的针对具体版本库的独享式忽略文件

即在版本库.git目录下的文件info/exclude中设置文件忽略

3. 本地的全局的独享式忽略文件

通过Git的配置变量core.excludesfile指定的一个忽略文件(指定文件名),其设置的忽略对所有本地版本库均有效。设置方法如下(文件名可以任意设置):

git config --global core.excludesfile ~/.gitignore

二、关于Git的忽略文件的语法规则

忽略文件中的空行或以井号(#)开始的行将会被忽略。
可以使用Linux通配符。例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围,大括号({string1,string2,...})代表可选的字符串等。
如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略。
如果名称的最前面是一个路径分隔符(/),表示要忽略的文件在此目录下,而子目录中的文件不忽略。
如果名称的最后面是一个路径分隔符(/),表示要忽略的是此目录下该名称的子目录,而非文件(默认文件或目录都忽略)。
示例:

# 这是注释行,将被忽略
*.a # 忽略所有以.a为扩展名的文件
!lib.a # 但是名为lib.a的文件或目录不要忽略,即使前面设置了对*.a的忽略
/TODO # 只忽略此目录下的TODO文件,子目录中的TODO文件不忽略
build/ # 忽略所有build目录下的文件,但如果是名为build的文件则不忽略
doc/*.txt # 忽略文件如doc/notes.txt,但是文件如doc/server/arch.txt不忽略


其他的一些过滤条件
?:代表任意的一个字符
*:代表任意数目的字符
{!ab}:必须不是此类型
{ab,bb,cx}:代表ab,bb,cx中任一类型即可
[abc]:代表a,b,c中任一字符即可
[ ^abc]:代表必须不是a,b,c中任一字符

============================================================================================
sparse-checkout 文件 指定要checkout 的目录

子目录的匹配在 sparse-checkout 文件中,如果目录名称前带斜杠,如/docs/,将只匹配项目根目录下的docs目录,
如果目录名称前不带斜杠,如docs/,其他目录下如果也有这个名称的目录,如test/docs/也能被匹配。
如果写了多级目录,如docs/05/,则不管前面是否带有斜杠,都只匹配项目根目录下的目录,如test/docs/05/ 不能被匹配。

在 sparse-checkout 文件中,支持通配符 *,如可以写成以下格式:
*docs
/index.*
*.gif

排除项 “!” (感叹号)在 sparse-checkout 文件中,也支持排除项 “!”,如只想排除排除项目下的 “docs” 目录,可以按如下格式写:
/*
!/docs/

很像 .gitignore的写法, 要注意一点:如果要关闭sparsecheckout功能,全取整个项目库,可以写一个”“号,但如果有排除项,必须写”/“,同时排除项要写在通配符后面。

要关闭 sparse checkout功 能,仅仅将core.sparsecheckout设为false是不生效的,需要修改 .git/info/sparse-checkout 文件,用一个'*'号替代其中的内容,然后执行 checkout 或 read-tree 命令。


以Tensorflow Models 为例分享一下:
git init models
cd models
git config core.sparsecheckout true //设置允许克隆子目录
echo official/resnet/* >> .git/info/sparse-checkout //设置要克隆的仓库的子目录路径
git remote add origin https://github.com/tensorflow/models
git pull origin branchName // 每次都用这个命令更新代码(只拉取指定分支branchName合并到当前本地分支,避免取下太多不会修改到的分支)

这种方法的git pull origin master存疑,我遇到过error: Sparse checkout leaves no entry on the working directory的错误,拉出了部分其它目录

按照下一方法的git checkout master则没有出现错误。(我使用时仍发现有错误,拉出了少量不相关的目录代码)
StackOverflow的分享:
cd tensorflow
git clone -n https://github.com/tensorflow/models . // -n 指定暂不checkout
git config core.sparsecheckout true
echo official/resnet >> .git/info/sparse-checkout
git checkout master

值得注意的是,无论哪种方法都需要下载.git文件夹,这是git的元数据存储。

============================================================================================

GIT 仓库瘦身

由于.git过大,我们可以从两种方向去思考,第一种治标不治本的方法:压缩git仓库。第二种删除git提交记录中大文件,在gc压缩。

第一种方法是比较直接快捷的,可以使用命令:git gc --prune=now

当你再次du -hs的时候会发现仓库大小有一定的变小。其实git自身在可承受范围内会自动用gc帮你压缩打包,所以除非真的遇到pull,push都困难的时候,可以不用手动执行。

这个方法明显的缺点在于压缩的效果有限,且大文件还一直在之后的每次提交中,为以后埋下隐患。

本人更推荐第二种方法,大文件对象再删除。

先查找大文件,命令如下:git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"

例如删除 nspatientList1.txt 文件:

git filter-branch --force --index-filter 'git rm -rf --cached --ignore-unmatch bin/nspatientList1.txt' --prune-empty --tag-name-filter cat -- --s

删除之后会有大量输出,显示已经从各自历史log中剔除掉关于这个大文件的信息,之后可以使用gc命令再次压缩: git gc --prune=now ,然后再进行提交即可。

你再次使用du相关命令检测文件夹大小会惊奇地发现大幅度缩小。当然也有人会说,这是你不断地粗鲁地merge造成的结果,所以也可以去使用rebase命令来衍合你的分支代码,让整个历史log变成干净清晰的一条直线。

============================================================================================

常用 Git 命令清单。几个专用名词的译名如下。

Workspace: 工作区
Index / Stage: 暂存区
Repository: 仓库区(或本地仓库)
Remote: 远程仓库
________ ___________
( ) ____________ | |
( ) -----------------(------------)--- pull (fetch + merge) ----->| |
( ) ( ) | |
( Remote ) --fetch/clone--> ( ) ----------checkout----------->| workspace |
( ) ( Repository ) | |
(________) <------push----- (___________ ) <--commit-- ( index ) <--add--| _________ |

一、新建代码库
# 在当前目录新建一个Git代码库
$ git init

# 新建一个目录,将其初始化为Git代码库
$ git init [project-name]

# 下载一个项目和它的整个代码历史
$ git clone [-b branch-name] [url]


二、配置
Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。

# 显示当前的Git配置
$ git config --list

# 编辑Git配置文件
$ git config -e [--global]

# 设置提交代码时的用户信息
$ git config [--global] user.name "[name]"
$ git config [--global] user.email "[email address]"


三、增加/删除文件

# 添加指定文件到暂存区
$ git add [file1] [file2] ...

# 添加指定目录到暂存区,包括子目录
$ git add [dir]

# 添加当前目录的所有文件到暂存区
$ git add .

# 添加每个变化前,都会要求确认
# 对于同一个文件的多处变化,可以实现分次提交
$ git add -p

# 删除工作区文件,并且将这次删除放入暂存区
$ git rm [file1] [file2] ...

# 停止追踪指定文件,但该文件会保留在工作区
$ git rm --cached [file]

# 改名文件,并且将这个改名放入暂存区
$ git mv [file-original] [file-renamed]


四、代码提交

# 提交暂存区到仓库区
$ git commit -m [message]

# 提交暂存区的指定文件到仓库区
$ git commit [file1] [file2] ... -m [message]

# 提交工作区自上次commit之后的变化,直接到仓库区
$ git commit -a

# 提交时显示所有diff信息
$ git commit -v

# 使用一次新的commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
$ git commit --amend -m [message]

# 重做上一次commit,并包括指定文件的新变化
$ git commit --amend [file1] [file2] ...

# 改变提交作者
$ git commit --author=zengzhigang

五、分支

# 列出所有本地分支
$ git branch

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

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

# 新建一个分支,但依然停留在当前分支
$ git branch [branch-name]

# 新建一个分支,并切换到该分支
$ git checkout -b [branch]

# 新建一个分支,指向指定commit
$ git branch [branch] [commit]

# 新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]

# 切换到指定分支,并更新工作区
$ git checkout [branch-name]

# 切换到上一个分支
$ git checkout -

# 建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream-to [branch] [remote-branch]

$ git branch -u [remote-branch]

# 合并指定分支到当前分支
$ git merge [branch]

A分支合并B分支,并强制使用B分支代码(不手动解决冲突)
git checkout A
git merge --strategy-option=theirs B

A分支合并B分支,并强制使用A分支代码(不手动解决冲突)
git checkout A
git merge --strategy-option=ours B

# 选择一个commit,合并进当前分支
$ git cherry-pick [commit]

# 删除分支
$ git branch -d [branch-name]

# 删除远程分支
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]

# 重命名本地分支
$ git branch -m devel develop

# 查看本地分支和远程分支的跟踪关系
$ git branch -vv
develop 08775f9 [origin/develop] develop
feature_1 b41865d [origin/feature_1] feature_1
* master 1399706 [my_github/master] init commit

develop分支跟踪origin/develop
feature_1分支跟踪origin/feature_1
master跟踪了my_github/master,且当前分支为master分支

六、标签

# 列出所有tag or git tag [-l]
$ git tag

# 新建一个tag在当前commit
$ git tag [tag]

# 新建一个tag在指定commit
$ git tag [tag] [commit]

# 打标签
git tag -a v1.01 -m "Relase version 1.01"

-a 是添加标签,其后要跟新标签号,-m 及后面的字符串是对该标签的注释

git tag -a brain-1.0.129-ai -m "brain-1.0.129-ai"
git push origin v1.0
git push origin --tags

# 删除本地tag
$ git tag -d [tag]

# 删除远程tag
$ git push origin :refs/tags/[tagName]
or
git push origin --delete tag <tagname>

# 获取远程tag
$ git fetch origin tag <tagname>

# 查看tag信息
$ git show [tag]

# 提交指定tag : 通常的git push不会将标签对象提交到git服务器,只有通过显式命令才能分享标签到远端仓库。
$ git push [remote] [tag]

# 提交所有tag
$ git push [remote] --tags

打开tortoiseGit的Revision graph功能,可以看到本地已经有该tag出现了.
tortiseGit打tag,没有单独推送tag的功能,我们只需要把打了tag的分支push到远程,并且在push的时候选中Include tag选项,就可以把分支和分支附属的tag一起推送到远程了。

# 新建一个分支,指向某个tag
$ git checkout -b [branch] [tag]


七、查看信息

# 显示有变更的文件
$ git status

git status -uno // -u[<mode>] mode: no = 不显示未跟踪的文件; normal: 显示未跟踪的文件及目录; all: 显示所有文件

# 显示当前分支的版本历史
$ git log

# 显示commit历史,以及每次commit发生变更的文件
$ git log --stat

# 搜索提交历史,根据关键词
$ git log -S [keyword]

# 显示某个commit之后的所有变动,每个commit占据一行
$ git log [tag] HEAD --pretty=format:%s

# 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件
$ git log [tag] HEAD --grep feature

# 显示某个文件的版本历史,包括文件改名
$ git log --follow [file]
$ git whatchanged [file]

# 显示指定文件相关的每一次diff
$ git log -p [file] 可以显示每次提交的diff

# 显示过去5次提交
$ git log -5 --pretty --oneline

# 显示所有提交过的用户,按提交次数排序
$ git shortlog -sn

# 显示指定文件是什么人在什么时间修改过
$ git blame [file]

# 显示暂存区和工作区的差异 (工作区 --> 暂存区 --> 仓库)
$ git diff

# 显示暂存区和上一个commit的差异
$ git diff --cached [file]

# 显示工作区与当前分支最新commit之间的差异
$ git diff HEAD

# 显示两次提交之间的差异
$ git diff [first-branch]...[second-branch]

# 显示今天你写了多少行代码
$ git diff --shortstat "@{0 day ago}"

# 显示某次提交的元数据和内容变化
$ git show [commit]

# 显示某次提交发生变化的文件
$ git show --name-only [commit]

# 显示某次提交时,某个文件的内容
$ git show [commit]:[filename]

# 显示当前分支的最近几次提交
$ git reflog

八、远程同步
# 下载远程仓库的所有变动
$ git fetch [remote]

# 显示所有远程仓库
$ git remote -v

# 显示某个远程仓库的信息
$ git remote show [remote]

# 增加一个新的远程仓库,并命名
$ git remote add [shortname] [url]

# 取回远程仓库的变化,并与本地分支合并
$ git pull [remote] [branch]

# 上传本地指定分支到远程仓库
$ git push [remote] [branch]

# 强行推送当前分支到远程仓库,即使有冲突
$ git push [remote] --force

# 推送所有分支到远程仓库
$ git push [remote] --all

$将新创建的分支信息推送到远程仓库, 并建立跟踪关系
$ git push origin HEAD -u

九、撤销
# 恢复暂存区的指定文件到工作区
$ git checkout [file]

# 恢复某个commit的指定文件到暂存区和工作区
$ git checkout [commit] [file]

# 恢复暂存区的所有文件到工作区
$ git checkout .

# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
$ git reset [file]

# 重置暂存区与工作区,与上一次commit保持一致
$ git reset --hard

# 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
$ git reset [commit]

# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
$ git reset --hard [commit]

# 重置当前HEAD为指定commit,但保持暂存区和工作区不变
$ git reset --keep [commit]

# 新建一个commit,用来撤销指定commit, 后者的所有变化都将被前者抵消,并且应用到当前分支
$ git revert [commit]

# 暂时将未提交的变化移除,稍后再移入
$ git stash
$ git stash pop


"git restore <file>..." to discard changes in working directory)

十、其他
# 生成一个可供发布的压缩包
$ git archive

git archive [--format=<fmt>] [--list] [--prefix=<prefix>/] [<extra>]
[-o <file> | --output=<file>] [--worktree-attributes]
[--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
[<path>…​]

# 将 master 以zip格式打包到指定文件
git archive --format zip --output /path/to/file.zip master

还有个更简单的
git archive v0.1 | gzip > site.tgz

git archive master > /home/hainuo/fds.zip

还有一个增量的
#比较develop分支上两个版本之间的差异文件,生成一个差异文件压缩包
git archive develop $( git diff v1.1.8_beta13..v1.1.8_beta14 --name-only)|gzip > aaa.zip


EXAMPLES
git archive --format=tar --prefix=junk/ HEAD | (cd /var/tmp/ && tar xf -)
Create a tar archive that contains the contents of the latest commit on the current branch, and extract it in the /var/tmp/junk directory.

git archive --format=tar --prefix=git-1.4.0/ v1.4.0 | gzip >git-1.4.0.tar.gz
Create a compressed tarball for v1.4.0 release.

git archive --format=tar.gz --prefix=git-1.4.0/ v1.4.0 >git-1.4.0.tar.gz
Same as above, but using the builtin tar.gz handling.

git archive --prefix=git-1.4.0/ -o git-1.4.0.tar.gz v1.4.0
Same as above, but the format is inferred from the output file.

git archive --format=tar --prefix=git-1.4.0/ v1.4.0^{tree} | gzip >git-1.4.0.tar.gz
Create a compressed tarball for v1.4.0 release, but without a global extended pax header.

git archive --format=zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs.zip
Put everything in the current head’s Documentation/ directory into git-1.4.0-docs.zip, with the prefix git-docs/.

git archive -o latest.zip HEAD
Create a Zip archive that contains the contents of the latest commit on the current branch. Note that the output format is inferred by the extension of the output file.

git config tar.tar.xz.command "xz -c"
Configure a "tar.xz" format for making LZMA-compressed tarfiles. You can use it specifying --format=tar.xz, or by creating an output file like -o foo.tar.xz.

============================================================================================
Git修改文件权限方法

查看Repository中文件权限,进入到要看的文件目录,输入git ls-tree HEAD

git ls-tree HEAD
100644 blob xxxxxxxxxxx file

修改权限
git update-index --chmod=+x file // 权限修改后,相当于文件进入了index中。

提交修改
$ git commit -m "revise permission access"
[master e5b2b16] revise permission access
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100755 gradlew

git ls-tree HEAD
100755 blob xxxxxxxxxxx file

Git客户端配置如下,可以避免文件权限改变。
git config core.filemode false

linux改变文件权限,直接在命令行终端运行,chmod 644 filename
windows改变文件权限,在git命令行终端运行,chmod 644 filename

Git客户端配置如下,可以避免换行符自动转换。
git config --global core.autocrlf false

windows上设置为 true, 签出代码时,LF会被转换成CRLF
如果你是Windows程序员,且正在开发仅运行在Windows上的项目,可以设置false取消此功能,把回车符记录在库中:

linux上设置成input来告诉 Git 在提交时把CRLF转换成LF,签出时不转换


git修改提交的用户名和Email

有时候在执行repo upload上传代码的时候会出现
To ssh://username@code.address.com:29442/kernel/msm
! [remote rejected] ltr558 -> refs/for/JB8X25_FC/IHV-LITEON-LTR-558ALS (you are not committer username@email.com)
error: failed to push some refs to 'ssh://username@code.address.com:29442/kernel/msm'

----------------------------------------------------------------------
[FAILED] kernel/ ltr558 (Upload failed)

这是因为之前git commit已提交的Email和现在正要提交的Email冲突,把它改成一致就OK了。

git commit已提交的Author信息可以通过git log查看

git config --global user.name "Your Name"
git config --global user.email you@example.com
全局的通过vim ~/.gitconfig来查看

git config user.name "Your Name"
git config user.email you@example.com
局部的通过当前路径下的 .git/config文件来查看

也可以修改提交的用户名和Email:
git commit --amend --author='Your Name '

============================================================================================

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

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

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

二、SafeCRLF

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

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

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


============================================================================================
git恢复删除文件之ls-files

如果一个文件不小心被删除了,可以有两种方法恢复:

1、需要记住所需恢复文件的名字和版本号(commit id)

git checkout commit_id -- file_name

如果不加commit_id,那么git checkout -- file_name 表示恢复文件到本地版本库中最新的状态。

 

2、不需要记住所需恢复的文件名字。

采用git ls-files命令,来看看这个命令的帮助信息:
$ git ls-files -h
usage: git ls-files [<options>] [<file>...]

-z paths are separated with NUL character
-t identify the file status with tags
-v use lowercase letters for 'assume unchanged' files
-f use lowercase letters for 'fsmonitor clean' files
-c, --cached show cached files in the output (default)
-d, --deleted show deleted files in the output
-m, --modified show modified files in the output
-o, --others show other files in the output
-i, --ignored show ignored files in the output
-s, --stage show staged contents' object name in the output
-k, --killed show files on the filesystem that need to be removed
--directory show 'other' directories' names only
--eol show line endings of files
--empty-directory don't show empty directories
-u, --unmerged show unmerged files in the output
--resolve-undo show resolve-undo information
-x, --exclude <pattern>
skip files matching pattern
-X, --exclude-from <file>
exclude patterns are read from <file>
--exclude-per-directory <file>
read additional per-directory exclude patterns in <file>
--exclude-standard add the standard git exclusions
--full-name make the output relative to the project top directory
--recurse-submodules recurse through submodules
--error-unmatch if any <file> is not in the index, treat this as an error
--with-tree <tree-ish>
pretend that paths removed since <tree-ish> are still present
--abbrev[=<n>] use <n> digits to display SHA-1s
--debug show debugging data


要查看删除的文件: git ls-files --deleted

使用命令checkout来恢复:git checkout -- file_name

如果要恢复多个被删除的文件,可以使用批处理命令:

git ls-files -d | xargs git checkout --

如果要恢复被修改的文件,命令:git ls-files -m | xargs git checkout --
-----------------------------------------

1.git pull会使用git merge导致冲突,需要将冲突的文件resolve掉, 再 git add -u, git commit之后才能成功pull.

2.如果想放弃本地的文件修改,可以使用git reset --hard FETCH_HEAD,FETCH_HEAD表示上一次成功 git pull 之后形成的commit点。然后git pull.

-----------------------------------------------------
查看某个文件的详细修改记录: git log -p files

============================================================================================

windows 系统下拉的android代码报 error: Invalid path 'compile/slang/tests/P_str_escape/str\\escape.rs'

解决办法:git stash 放入暂存区不再恢复它即可。

git rebase 失败的处理方法:
git pull; git reset --hard HEAD^ // 前提是本地没有新的提交

先直接更新,再重置到HEAD的前一个提交(这个HEAD是pull后本地差异生成的一个提交,不需要它)

git clone 失败的处理方法:
zengzhigang@ubuntu:~/wifibox/QK_WiFi_ESP32$ git clone ssh://zengzhigang@10.100.13.21:29418/MQTT_Client_WiFi
Cloning into 'MQTT_Client_WiFi'...
The authenticity of host '[10.100.13.21]:29418 ([10.100.13.21]:29418)' can't be established.
RSA key fingerprint is SHA256:lGM+jxse3Nnp0D3gU/ULOY+rIFU7zYgXdbBfjDPJ470.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[10.100.13.21]:29418' (RSA) to the list of known hosts.
zengzhigang@10.100.13.21: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
zengzhigang@ubuntu:~/wifibox/QK_WiFi_ESP32$

把服务器里面新生成的公钥,添加到21里面
重新生成公钥:ssh-keygen -t rsa(所有需要输入的地方选择回车即可),尽量都存放在默认的c盘路径,将新生成的公钥id_rsa.pub配到gerrit即可

zengzhigang@ubuntu:~/wifibox/QK_WiFi_ESP32$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/zengzhigang/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/zengzhigang/.ssh/id_rsa.
Your public key has been saved in /home/zengzhigang/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:ocjCeYZrZmcsYgtq99UVd5UIASJwl6lvkKPPcN1oAv4 zengzhigang@ubuntu
The key's randomart image is:
+---[RSA 2048]----+
| ..o oo..oo . o|
| . oo. . ..|
| o . . . . |
| . = * . . o . |
| * B * S . |
| X o *... |
|o.* X +. . |
|+*.= E. |
|o.. .. |
+----[SHA256]-----+

把/home/zengzhigang/.ssh目录下的id_rsa.pub 公钥放到 gerrit


============================================================================================
git中出现remote: HTTP Basic: Access denied

1. 如果账号密码有变动 用这个命令 git config –-system –-unset credential.helper 重新输入账号密码 应该就能解决了
2. 如果用了第一个命令 还不能解决问题那么 用这个命令: git config –-global http.emptyAuth true
3. 原因: 远程服务端的用户名和密码与当前系统中git保存的用户名和密码有冲突

需要管理员权限
$ git config --system --unset credential.helper
error: could not lock config file C:/Program Files/Git/mingw64/etc/gitconfig: Permission denied


git config --global credential.helper store 永久保存账户密码

============================================================================================

但是用这种操作步骤我这里是必现,这里说下解决方案:

git 出现 error Missing tree 的处理办法

error: unpack failed: error Missing tree 129d587458f56f4b1f9c492824a97dc717257516
fatal: Unpack error, check server log

git push --no-thin origin HEAD:refs/for/currentbranch

解释:关键点是--no-thin选项,默认情况下,git push会在向服务器推送时进行优化,以将所发送的包降低到最小。
做法是发送时忽略本地仓库和远端仓库中共有的部分。即git push默认是采用--thin选项的

============================================================================================
.gitmodules详解(Git子模块配置)

一、gitmodules是什么
子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。

二、如何使用gitmodules
$ git submodule add https://github.com/XXX
默认情况下,子模块会将子项目放到一个与仓库同名的目录中,即“XXX”。 如果你想要放到其他地方,那么可以在命令结尾添加一个不同的路径。

如果这时运行 git status,注意到新的.gitmodules文件。 该配置文件保存了项目 URL 与已经拉取的本地目录之间的映射,
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

new file: .gitmodules
new file: XXX

如果想进一步指定分支,可以增加-b参数,详细参考如下:
$ git submodule add
usage: git submodule [--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
or: git submodule [--quiet] status [--cached] [--recursive] [--] [<path>...]
or: git submodule [--quiet] init [--] [<path>...]
or: git submodule [--quiet] deinit [-f|--force] (--all| [--] <path>...)
or: git submodule [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]
or: git submodule [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
or: git submodule [--quiet] foreach [--recursive] <command>
or: git submodule [--quiet] sync [--recursive] [--] [<path>...]
or: git submodule [--quiet] absorbgitdirs [--] [<path>...]

三、.gitmodules配置
[submodule "abc"]
path = abc
url = http://github.xxx.xxx/xxxx
branch = release
============================================================================================
开发过程中,经常会有一些通用的部分希望抽取出来做成一个公共库来提供给别的工程来使用,而公共代码库的版本管理是个麻烦的事情。今天无意中发现了git的git submodule命令,之前的问题迎刃而解了。

添加
为当前工程添加submodule,命令如下:

git submodule add 仓库地址 路径

其中,仓库地址是指子模块仓库地址,路径指将子模块放置在当前工程下的路径。
注意:路径不能以 / 结尾(会造成修改不生效)、不能是现有工程已有的目录(不能順利 Clone)

命令执行完成,会在当前工程根路径下生成一个名为“.gitmodules”的文件,其中记录了子模块的信息。添加完成以后,再将子模块所在的文件夹添加到工程中即可。

删除
submodule的删除稍微麻烦点:首先,要在“.gitmodules”文件中删除相应配置信息。然后,执行“git rm –cached ”命令将子模块所在的文件从git中删除。

下载的工程带有submodule
当使用git clone下来的工程中带有submodule时,初始的时候,submodule的内容并不会自动下载下来的,此时,只需执行如下命令:

git submodule update --init --recursive

即可将子模块内容下载下来后工程才不会缺少相应的文件。

 

子仓库操作
git submodule init --recursive --remote
git submodule update
============================================================================================
============================================================================================
============================================================================================
============================================================================================
============================================================================================
============================================================================================
下面是 git help

$ git remote -h
usage: git remote [-v | --verbose]
or: git remote add [-t <branch>] [-m <master>] [-f] [--tags | --no-tags] [--mirror=<fetch|push>] <name> <url>
or: git remote rename <old> <new>
or: git remote remove <name>
or: git remote set-head <name> (-a | --auto | -d | --delete | <branch>)
or: git remote [-v | --verbose] show [-n] <name>
or: git remote prune [-n | --dry-run] <name>
or: git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]
or: git remote set-branches [--add] <name> <branch>...
or: git remote get-url [--push] [--all] <name>
or: git remote set-url [--push] <name> <newurl> [<oldurl>]
or: git remote set-url --add <name> <newurl>
or: git remote set-url --delete <name> <url>

-v, --verbose be verbose; must be placed before a subcommand

add:
With -f option, git fetch <name> is run immediately after the remote information is set up.

With -t <branch> option, instead of the default glob refspec for the remote to track all branches under the refs/remotes/<name>/ namespace,
a refspec to track only <branch> is created. You can give more than one -t <branch> to track multiple branches without grabbing all branches.

With -t <branch> option, instead of the default glob refspec for the remote to track all branches under the refs/remotes/<name>/ namespace,
a refspec to track only <branch> is created. You can give more than one -t <branch> to track multiple branches without grabbing all branches.

With -m <master> option, a symbolic-ref refs/remotes/<name>/HEAD is set up to point at remote’s <master> branch. See also the set-head command.

When a fetch mirror is created with --mirror=fetch, the refs will not be stored in the refs/remotes/ namespace,
but rather everything in refs/ on the remote will be directly mirrored into refs/ in the local repository.
This option only makes sense in bare repositories, because a fetch would overwrite any local commits.

When a push mirror is created with --mirror=push, then git push will always behave as if --mirror was passed.
============================================================================================

$ git blame

usage: git blame [<options>] [<rev-opts>] [<rev>] [--] <file>
<rev-opts> are documented in git-rev-list(1)

--incremental Show blame entries as we find them, incrementally
-b Show blank SHA-1 for boundary commits (Default: off)
--root Do not treat root commits as boundaries (Default: off)
--show-stats Show work cost statistics
--progress Force progress reporting
--score-debug Show output score for blame entries
-f, --show-name Show original filename (Default: auto)
-n, --show-number Show original linenumber (Default: off)
-p, --porcelain Show in a format designed for machine consumption
--line-porcelain Show porcelain format with per-line commit information
-c Use the same output mode as git-annotate (Default: off)
-t Show raw timestamp (Default: off)
-l Show long commit SHA1 (Default: off)
-s Suppress author name and timestamp (Default: off)
-e, --show-email Show author email instead of name (Default: off)
-w Ignore whitespace differences
--indent-heuristic Use an experimental indent-based heuristic to improve diffs
--compaction-heuristic
Use an experimental blank-line-based heuristic to improve diffs
--minimal Spend extra cycles to find better match
-S <file> Use revisions from <file> instead of calling git-rev-list
--contents <file> Use <file>'s contents as the final image
-C[<score>] Find line copies within and across files
-M[<score>] Find line movements within and across files
-L <n,m> Process only line range n,m, counting from 1
--abbrev[=<n>] use <n> digits to display SHA-1s

============================================================================================

$ git fetch -h

usage: git fetch [<options>] [<repository> [<refspec>...]]
or: git fetch [<options>] <group>
or: git fetch --multiple [<options>] [(<repository> | <group>)...]
or: git fetch --all [<options>]

-v, --verbose be more verbose
-q, --quiet be more quiet
--all fetch from all remotes
-a, --append append to .git/FETCH_HEAD instead of overwriting
--upload-pack <path> path to upload pack on remote end
-f, --force force overwrite of local reference
-m, --multiple fetch from multiple remotes
-t, --tags fetch all tags and associated objects
-n do not fetch all tags (--no-tags)
-j, --jobs <n> number of submodules fetched in parallel
-p, --prune prune remote-tracking branches no longer on remote
-P, --prune-tags prune local tags no longer on remote and clobber changed tags
--recurse-submodules[=<on-demand>]
control recursive fetching of submodules
--dry-run dry run
-k, --keep keep downloaded pack
-u, --update-head-ok allow updating of HEAD ref
--progress force progress reporting
--depth <depth> deepen history of shallow clone
--shallow-since <time>
deepen history of shallow repository based on time
--shallow-exclude <revision>
deepen history of shallow clone, excluding rev
--deepen <n> deepen history of shallow clone
--unshallow convert to a complete repository
--update-shallow accept refs that update .git/shallow
--refmap <refmap> specify fetch refmap
-o, --server-option <server-specific>
option to transmit
-4, --ipv4 use IPv4 addresses only
-6, --ipv6 use IPv6 addresses only
--negotiation-tip <revision>
report that we have only objects reachable from this object
--filter <args> object filtering


============================================================================================

$ git pull -h
usage: git pull [<options>] [<repository> [<refspec>...]]

-v, --verbose be more verbose
-q, --quiet be more quiet
--progress force progress reporting
--recurse-submodules[=<on-demand>]
control for recursive fetching of submodules

Options related to merging
-r, --rebase[=<false|true|preserve|interactive>]
incorporate changes by rebasing rather than merging
-n do not show a diffstat at the end of the merge
--stat show a diffstat at the end of the merge
--log[=<n>] add (at most <n>) entries from shortlog to merge commit message
--squash create a single commit instead of doing a merge
--commit perform a commit if the merge succeeds (default)
--edit edit message before committing
--ff allow fast-forward
--ff-only abort if fast-forward is not possible
--verify-signatures verify that the named commit has a valid GPG signature
--autostash automatically stash/stash pop before and after rebase
-s, --strategy <strategy>
merge strategy to use
-X, --strategy-option <option=value>
option for selected merge strategy
-S, --gpg-sign[=<key-id>]
GPG sign commit
--allow-unrelated-histories
allow merging unrelated histories

Options related to fetching
--all fetch from all remotes
-a, --append append to .git/FETCH_HEAD instead of overwriting
--upload-pack <path> path to upload pack on remote end
-f, --force force overwrite of local branch
-t, --tags fetch all tags and associated objects
-p, --prune prune remote-tracking branches no longer on remote
-j, --jobs[=<n>] number of submodules pulled in parallel
--dry-run dry run
-k, --keep keep downloaded pack
--depth <depth> deepen history of shallow clone
--unshallow convert to a complete repository
--update-shallow accept refs that update .git/shallow
--refmap <refmap> specify fetch refmap
============================================================================================
$ git push -h
usage: git push [<options>] [<repository> [<refspec>...]]

-v, --verbose be more verbose
-q, --quiet be more quiet
--repo <repository> repository
--all push all refs
--mirror mirror all refs
--delete delete refs
--tags push tags (can't be used with --all or --mirror)
-n, --dry-run dry run
--porcelain machine-readable output
-f, --force force updates
--force-with-lease[=<refname>:<expect>]
require old value of ref to be at this value
--recurse-submodules[=<check>]
control recursive pushing of submodules
--thin use thin pack
--receive-pack <receive-pack>
receive pack program
--exec <receive-pack>
receive pack program
-u, --set-upstream set upstream for git pull/status
--progress force progress reporting
--prune prune locally removed refs
--no-verify bypass pre-push hook
--follow-tags push missing but relevant tags
============================================================================================
$ git clone -h
usage: git clone [<options>] [--] <repo> [<dir>]

-v, --verbose be more verbose
-q, --quiet be more quiet
--progress force progress reporting
-n, --no-checkout don't create a checkout
--bare create a bare repository
--mirror create a mirror repository (implies bare)
-l, --local to clone from a local repository
--no-hardlinks don't use local hardlinks, always copy
-s, --shared setup as shared repository
--recurse-submodules[=<pathspec>]
initialize submodules in the clone
-j, --jobs <n> number of submodules cloned in parallel
--template <template-directory>
directory from which templates will be used
--reference <repo> reference repository
--reference-if-able <repo>
reference repository
--dissociate use --reference only while cloning
-o, --origin <name> use <name> instead of 'origin' to track upstream
-b, --branch <branch>
checkout <branch> instead of the remote's HEAD
-u, --upload-pack <path>
path to git-upload-pack on the remote
--depth <depth> create a shallow clone of that depth
--shallow-since <time>
create a shallow clone since a specific time
--shallow-exclude <revision>
deepen history of shallow clone, excluding rev
--single-branch clone only one branch, HEAD or --branch
--no-tags don't clone any tags, and make later fetches not to follow them
--shallow-submodules any cloned submodules will be shallow
--separate-git-dir <gitdir>
separate git dir from working tree
-c, --config <key=value>
set config inside the new repository
-4, --ipv4 use IPv4 addresses only
-6, --ipv6 use IPv6 addresses only

============================================================================================
$ git branch -h
usage: git branch [options] [-r | -a] [--merged | --no-merged]
or: git branch [options] [-l] [-f] <branchname> [<start-point>]
or: git branch [options] [-r] (-d | -D) <branchname>...
or: git branch [options] (-m | -M) [<oldbranch>] <newbranch>

Generic options
-v, --verbose show hash and subject, give twice for upstream branch
-q, --quiet suppress informational messages
-t, --track set up tracking mode (see git-pull(1))
--set-upstream change upstream info // 这个将废弃,改用 -t 或 -u
-u, --set-upstream-to <upstream>
change the upstream info
--unset-upstream Unset the upstream info
--color[=<when>] use colored output
-r, --remotes act on remote-tracking branches, List or delete (if used with -d) the remote-tracking branches.
--contains <commit> print only branches that contain the commit
--abbrev[=<n>] use <n> digits to display SHA-1s

Specific git-branch actions:
-a, --all list both remote-tracking and local branches
-d, --delete delete fully merged branch
-D delete branch (even if not merged)
-m, --move move/rename a branch and its reflog
-M move/rename a branch, even if target exists
--list list branch names
-l, --create-reflog create the branch's reflog
--edit-description edit the description for the branch
-f, --force force creation (when already exists)
--no-merged <commit> print only not merged branches
--merged <commit> print only merged branches
--column[=<style>] list branches in columns

============================================================================================
$ git remote -h
usage: git remote [-v | --verbose]
or: git remote add [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>
or: git remote rename <old> <new>
or: git remote remove <name>
or: git remote set-head <name> (-a | --auto | -d | --delete |<branch>)
or: git remote [-v | --verbose] show [-n] <name>
or: git remote prune [-n | --dry-run] <name>
or: git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]
or: git remote set-branches [--add] <name> <branch>...
or: git remote set-url [--push] <name> <newurl> [<oldurl>]
or: git remote set-url --add <name> <newurl>
or: git remote set-url --delete <name> <url>

-v, --verbose be verbose; must be placed before a subcommand
============================================================================================
$ git commit -h
usage: git commit [options] [--] <pathspec>...

-q, --quiet suppress summary after successful commit
-v, --verbose show diff in commit message template

Commit message options
-F, --file <file> read message from file
--author <author> override author for commit
--date <date> override date for commit
-m, --message <message>
commit message
-c, --reedit-message <commit>
reuse and edit message from specified commit
-C, --reuse-message <commit>
reuse message from specified commit
--fixup <commit> use autosquash formatted message to fixup specified commit
--squash <commit> use autosquash formatted message to squash specified commit
--reset-author the commit is authored by me now (used with -C/-c/--amend)
-s, --signoff add Signed-off-by:
-t, --template <file>
use specified template file
-e, --edit force edit of commit
--cleanup <default> how to strip spaces and #comments from message
--status include status in commit message template
-S, --gpg-sign[=<key id>]
GPG sign commit

Commit contents options
-a, --all commit all changed files
-i, --include add specified files to index for commit
--interactive interactively add files
-p, --patch interactively add changes
-o, --only commit only specified files
-n, --no-verify bypass pre-commit hook
--dry-run show what would be committed
--short show status concisely
--branch show branch information
--porcelain machine-readable output
--long show status in long format (default)
-z, --null terminate entries with NUL
--amend amend previous commit
--no-post-rewrite bypass post-rewrite hook
-u, --untracked-files[=<mode>]
show untracked files, optional modes: all, normal, no. (Default: all)
============================================================================================

$ git checkout -h
usage: git checkout [<options>] <branch>
or: git checkout [<options>] [<branch>] -- <file>...

-q, --quiet suppress progress reporting
-b <branch> create and checkout a new branch
-B <branch> create/reset and checkout a branch
-l create reflog for new branch
--detach detach HEAD at named commit
-t, --track set upstream info for new branch
--orphan <new-branch>
new unparented branch
-2, --ours checkout our version for unmerged files
-3, --theirs checkout their version for unmerged files
-f, --force force checkout (throw away local modifications)
-m, --merge perform a 3-way merge with the new branch
--overwrite-ignore update ignored files (default)
--conflict <style> conflict style (merge or diff3)
-p, --patch select hunks interactively
--ignore-skip-worktree-bits
do not limit pathspecs to sparse entries only
--ignore-other-worktrees
do not check if another worktree is holding the given ref
--progress force progress reporting

============================================================================================
$ git gc -h
usage: git gc [<options>]

-q, --quiet suppress progress reporting
--prune[=<date>] prune unreferenced objects
--aggressive be more thorough (increased runtime)
--auto enable auto-gc mode
--force force running gc even if there may be another gc running

============================================================================================
$ git fsck -h
usage: git fsck [<options>] [<object>...]

-v, --verbose be verbose
--unreachable show unreachable objects
--dangling show dangling objects
--tags report tags
--root report root nodes
--cache make index objects head nodes
--reflogs make reflogs head nodes (default)
--full also consider packs and alternate objects
--connectivity-only check only connectivity
--strict enable more strict checking
--lost-found write dangling objects in .git/lost-found
--progress show progress
--name-objects show verbose names for reachable objects

============================================================================================
$ git tag -h
usage: git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]
<tagname> [<head>]
or: git tag -d <tagname>...
or: git tag -l [-n[<num>]] [--contains <commit>] [--no-contains <commit>] [--points-at <object>]
[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]
or: git tag -v [--format=<format>] <tagname>...

-l, --list list tag names
-n[<n>] print <n> lines of each tag message
-d, --delete delete tags
-v, --verify verify tags

Tag creation options
-a, --annotate annotated tag, needs a message
-m, --message <message>
tag message
-F, --file <file> read message from file
-e, --edit force edit of tag message
-s, --sign annotated and GPG-signed tag
--cleanup <mode> how to strip spaces and #comments from message
-u, --local-user <key-id>
use another key to sign the tag
-f, --force replace the tag if exists
--create-reflog create a reflog

Tag listing options
--column[=<style>] show tag list in columns
--contains <commit> print only tags that contain the commit
--no-contains <commit>
print only tags that don't contain the commit
--merged <commit> print only tags that are merged
--no-merged <commit> print only tags that are not merged
--sort <key> field name to sort on
--points-at <object> print only tags of the object
--format <format> format to use for the output
--color[=<when>] respect format colors
-i, --ignore-case sorting and filtering are case insensitive

============================================================================================
$ git merge -h
usage: git merge [<options>] [<commit>...]
or: git merge --abort
or: git merge --continue

-n do not show a diffstat at the end of the merge
--stat show a diffstat at the end of the merge
--summary (synonym to --stat)
--log[=<n>] add (at most <n>) entries from shortlog to merge commit message
--squash create a single commit instead of doing a merge
--commit perform a commit if the merge succeeds (default)
-e, --edit edit message before committing
--cleanup <mode> how to strip spaces and #comments from message
--ff allow fast-forward (default)
--ff-only abort if fast-forward is not possible
--rerere-autoupdate update the index with reused conflict resolution if possible
--verify-signatures verify that the named commit has a valid GPG signature
-s, --strategy <strategy>
merge strategy to use
-X, --strategy-option <option=value>
option for selected merge strategy
-m, --message <message>
merge commit message (for a non-fast-forward merge)
-F, --file <path> read message from file
-v, --verbose be more verbose
-q, --quiet be more quiet
--abort abort the current in-progress merge
--quit --abort but leave index and working tree alone
--continue continue the current in-progress merge
--allow-unrelated-histories
allow merging unrelated histories
--progress force progress reporting
-S, --gpg-sign[=<key-id>]
GPG sign commit
--autostash automatically stash/stash pop before and after
--overwrite-ignore update ignored files (default)
--signoff add Signed-off-by:
--no-verify bypass pre-merge-commit and commit-msg hooks

============================================================================================
git rebase --help
GIT-REBASE(1) Git Manual GIT-REBASE(1)

NAME
git-rebase - Forward-port local commits to the updated upstream head

SYNOPSIS
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
[<upstream>] [<branch>]
git rebase [-i | --interactive] [options] [--exec <cmd>] [--onto <newbase>]
--root [<branch>]
git rebase --continue | --skip | --abort | --edit-todo

DESCRIPTION
If <branch> is specified, git rebase will perform an automatic git checkout <branch> before doing anything else. Otherwise it remains on the
current branch.

If <upstream> is not specified, the upstream configured in branch.<name>.remote and branch.<name>.merge options will be used; see git-config(1) for
details. If you are currently not on any branch or if the current branch does not have a configured upstream, the rebase will abort.

All changes made by commits in the current branch but that are not in <upstream> are saved to a temporary area. This is the same set of commits
that would be shown by git log <upstream>..HEAD (or git log HEAD, if --root is specified).

The current branch is reset to <upstream>, or <newbase> if the --onto option was supplied. This has the exact same effect as git reset --hard
<upstream> (or <newbase>). ORIG_HEAD is set to point at the tip of the branch before the reset.

The commits that were previously saved into the temporary area are then reapplied to the current branch, one by one, in order. Note that any
commits in HEAD which introduce the same textual changes as a commit in HEAD..<upstream> are omitted (i.e., a patch already accepted upstream with
a different commit message or timestamp will be skipped).

It is possible that a merge failure will prevent this process from being completely automatic. You will have to resolve any such merge failure and
run git rebase --continue. Another option is to bypass the commit that caused the merge failure with git rebase --skip. To check out the original
<branch> and remove the .git/rebase-apply working files, use the command git rebase --abort instead.

Assume the following history exists and the current branch is "topic":

A---B---C topic
/
D---E---F---G master

From this point, the result of either of the following commands:

git rebase master
git rebase master topic

would be:

A'--B'--C' topic
/
D---E---F---G master

NOTE: The latter form is just a short-hand of git checkout topic followed by git rebase master. When rebase exits topic will remain the checked-out
branch.

If the upstream branch already contains a change you have made (e.g., because you mailed a patch which was applied upstream), then that commit will
be skipped. For example, running ‘git rebase master` on the following history (in which A’ and A introduce the same set of changes, but have
different committer information):

A---B---C topic
/
D---E---A'---F master

will result in:

B'---C' topic
/
D---E---A'---F master

Here is how you would transplant a topic branch based on one branch to another, to pretend that you forked the topic branch from the latter branch,
using rebase --onto.

First let’s assume your topic is based on branch next. For example, a feature developed in topic depends on some functionality which is found in
next.

o---o---o---o---o master
\
o---o---o---o---o next
\
o---o---o topic

We want to make topic forked from branch master; for example, because the functionality on which topic depends was merged into the more stable
master branch. We want our tree to look like this:

o---o---o---o---o master
| \
| o'--o'--o' topic
\
o---o---o---o---o next

We can get this using the following command:

git rebase --onto master next topic

Another example of --onto option is to rebase part of a branch. If we have the following situation:

H---I---J topicB
/
E---F---G topicA
/
A---B---C---D master

then the command

git rebase --onto master topicA topicB

would result in:

H'--I'--J' topicB
/
| E---F---G topicA
|/
A---B---C---D master

This is useful when topicB does not depend on topicA.

A range of commits could also be removed with rebase. If we have the following situation:

E---F---G---H---I---J topicA

then the command

git rebase --onto topicA~5 topicA~3 topicA

would result in the removal of commits F and G:

E---H'---I'---J' topicA

This is useful if F and G were flawed in some way, or should not be part of topicA. Note that the argument to --onto and the <upstream> parameter
can be any valid commit-ish.

In case of conflict, git rebase will stop at the first problematic commit and leave conflict markers in the tree. You can use git diff to locate
the markers (<<<<<<) and make edits to resolve the conflict. For each file you edit, you need to tell Git that the conflict has been resolved,
typically this would be done with

git add <filename>

After resolving the conflict manually and updating the index with the desired resolution, you can continue the rebasing process with

git rebase --continue

Alternatively, you can undo the git rebase with

git rebase --abort

CONFIGURATION
rebase.stat
Whether to show a diffstat of what changed upstream since the last rebase. False by default.

rebase.autosquash
If set to true enable --autosquash option by default.

rebase.autostash
If set to true enable --autostash option by default.

OPTIONS
--onto <newbase>
Starting point at which to create the new commits. If the --onto option is not specified, the starting point is <upstream>. May be any valid
commit, and not just an existing branch name.

As a special case, you may use "A...B" as a shortcut for the merge base of A and B if there is exactly one merge base. You can leave out at
most one of A and B, in which case it defaults to HEAD.

<upstream>
Upstream branch to compare against. May be any valid commit, not just an existing branch name. Defaults to the configured upstream for the
current branch.

<branch>
Working branch; defaults to HEAD.

--continue
Restart the rebasing process after having resolved a merge conflict.

--abort
Abort the rebase operation and reset HEAD to the original branch. If <branch> was provided when the rebase operation was started, then HEAD
will be reset to <branch>. Otherwise HEAD will be reset to where it was when the rebase operation was started.

--keep-empty
Keep the commits that do not change anything from its parents in the result.

--skip
Restart the rebasing process by skipping the current patch.

--edit-todo
Edit the todo list during an interactive rebase.

-m, --merge
Use merging strategies to rebase. When the recursive (default) merge strategy is used, this allows rebase to be aware of renames on the
upstream side.

Note that a rebase merge works by replaying each commit from the working branch on top of the <upstream> branch. Because of this, when a merge
conflict happens, the side reported as ours is the so-far rebased series, starting with <upstream>, and theirs is the working branch. In other
words, the sides are swapped.

-s <strategy>, --strategy=<strategy>
Use the given merge strategy. If there is no -s option git merge-recursive is used instead. This implies --merge.

Because git rebase replays each commit from the working branch on top of the <upstream> branch using the given strategy, using the ours
strategy simply discards all patches from the <branch>, which makes little sense.

-X <strategy-option>, --strategy-option=<strategy-option>
Pass the <strategy-option> through to the merge strategy. This implies --merge and, if no strategy has been specified, -s recursive. Note the
reversal of ours and theirs as noted above for the -m option.

-q, --quiet
Be quiet. Implies --no-stat.

-v, --verbose
Be verbose. Implies --stat.

--stat
Show a diffstat of what changed upstream since the last rebase. The diffstat is also controlled by the configuration option rebase.stat.

-n, --no-stat
Do not show a diffstat as part of the rebase process.

--no-verify
This option bypasses the pre-rebase hook. See also githooks(5).

--verify
Allows the pre-rebase hook to run, which is the default. This option can be used to override --no-verify. See also githooks(5).

-C<n>
Ensure at least <n> lines of surrounding context match before and after each change. When fewer lines of surrounding context exist they all
must match. By default no context is ever ignored.

-f, --force-rebase
Force the rebase even if the current branch is a descendant of the commit you are rebasing onto. Normally non-interactive rebase will exit with
the message "Current branch is up to date" in such a situation. Incompatible with the --interactive option.

You may find this (or --no-ff with an interactive rebase) helpful after reverting a topic branch merge, as this option recreates the topic
branch with fresh commits so it can be remerged successfully without needing to "revert the reversion" (see the revert-a-faulty-merge How-To[1]
for details).

--fork-point, --no-fork-point
Use git merge-base --fork-point to find a better common ancestor between upstream and branch when calculating which commits have have been
introduced by branch (see git-merge-base(1)).

If no non-option arguments are given on the command line, then the default is --fork-point @{u} otherwise the upstream argument is interpreted
literally unless the --fork-point option is specified.

--ignore-whitespace, --whitespace=<option>
These flag are passed to the git apply program (see git-apply(1)) that applies the patch. Incompatible with the --interactive option.

--committer-date-is-author-date, --ignore-date
These flags are passed to git am to easily change the dates of the rebased commits (see git-am(1)). Incompatible with the --interactive option.

-i, --interactive
Make a list of the commits which are about to be rebased. Let the user edit that list before rebasing. This mode can also be used to split
commits (see SPLITTING COMMITS below).

-p, --preserve-merges
Instead of ignoring merges, try to recreate them.

This uses the --interactive machinery internally, but combining it with the --interactive option explicitly is generally not a good idea unless
you know what you are doing (see BUGS below).

-x <cmd>, --exec <cmd>
Append "exec <cmd>" after each line creating a commit in the final history. <cmd> will be interpreted as one or more shell commands.

This option can only be used with the --interactive option (see INTERACTIVE MODE below).

You may execute several commands by either using one instance of --exec with several commands:

git rebase -i --exec "cmd1 && cmd2 && ..."

or by giving more than one --exec:

git rebase -i --exec "cmd1" --exec "cmd2" --exec ...

If --autosquash is used, "exec" lines will not be appended for the intermediate commits, and will only appear at the end of each squash/fixup
series.

--root
Rebase all commits reachable from <branch>, instead of limiting them with an <upstream>. This allows you to rebase the root commit(s) on a
branch. When used with --onto, it will skip changes already contained in <newbase> (instead of <upstream>) whereas without --onto it will
operate on every change. When used together with both --onto and --preserve-merges, all root commits will be rewritten to have <newbase> as
parent instead.

--autosquash, --no-autosquash
When the commit log message begins with "squash! ..." (or "fixup! ..."), and there is a commit whose title begins with the same ...,
automatically modify the todo list of rebase -i so that the commit marked for squashing comes right after the commit to be modified, and change
the action of the moved commit from pick to squash (or fixup). Ignores subsequent "fixup! " or "squash! " after the first, in case you referred
to an earlier fixup/squash with git commit --fixup/--squash.

This option is only valid when the --interactive option is used.

If the --autosquash option is enabled by default using the configuration variable rebase.autosquash, this option can be used to override and
disable this setting.

--[no-]autostash
Automatically create a temporary stash before the operation begins, and apply it after the operation ends. This means that you can run rebase
on a dirty worktree. However, use with care: the final stash application after a successful rebase might result in non-trivial conflicts.

--no-ff
With --interactive, cherry-pick all rebased commits instead of fast-forwarding over the unchanged ones. This ensures that the entire history of
the rebased branch is composed of new commits.

Without --interactive, this is a synonym for --force-rebase.

You may find this helpful after reverting a topic branch merge, as this option recreates the topic branch with fresh commits so it can be
remerged successfully without needing to "revert the reversion" (see the revert-a-faulty-merge How-To[1] for details).
MERGE STRATEGIES
The merge mechanism (git-merge and git-pull commands) allows the backend merge strategies to be chosen with -s option. Some strategies can also
take their own options, which can be passed by giving -X<option> arguments to git-merge and/or git-pull.

resolve
This can only resolve two heads (i.e. the current branch and another branch you pulled from) using a 3-way merge algorithm. It tries to
carefully detect criss-cross merge ambiguities and is considered generally safe and fast.

recursive
This can only resolve two heads using a 3-way merge algorithm. When there is more than one common ancestor that can be used for 3-way merge, it
creates a merged tree of the common ancestors and uses that as the reference tree for the 3-way merge. This has been reported to result in
fewer merge conflicts without causing mis-merges by tests done on actual merge commits taken from Linux 2.6 kernel development history.
Additionally this can detect and handle merges involving renames. This is the default merge strategy when pulling or merging one branch.

The recursive strategy can take the following options:

ours
This option forces conflicting hunks to be auto-resolved cleanly by favoring our version. Changes from the other tree that do not conflict
with our side are reflected to the merge result. For a binary file, the entire contents are taken from our side.

This should not be confused with the ours merge strategy, which does not even look at what the other tree contains at all. It discards
everything the other tree did, declaring our history contains all that happened in it.

theirs
This is the opposite of ours.

patience
With this option, merge-recursive spends a little extra time to avoid mismerges that sometimes occur due to unimportant matching lines
(e.g., braces from distinct functions). Use this when the branches to be merged have diverged wildly. See also git-diff(1)--patience.

diff-algorithm=[patience|minimal|histogram|myers]
Tells merge-recursive to use a different diff algorithm, which can help avoid mismerges that occur due to unimportant matching lines (such
as braces from distinct functions). See also git-diff(1)--diff-algorithm.

ignore-space-change, ignore-all-space, ignore-space-at-eol
Treats lines with the indicated type of whitespace change as unchanged for the sake of a three-way merge. Whitespace changes mixed with
other changes to a line are not ignored. See also git-diff(1)-b, -w, and --ignore-space-at-eol.

· If their version only introduces whitespace changes to a line, our version is used;

· If our version introduces whitespace changes but their version includes a substantial change, their version is used;

· Otherwise, the merge proceeds in the usual way.

renormalize
This runs a virtual check-out and check-in of all three stages of a file when resolving a three-way merge. This option is meant to be used
when merging branches with different clean filters or end-of-line normalization rules. See "Merging branches with differing
checkin/checkout attributes" in gitattributes(5) for details.

no-renormalize
Disables the renormalize option. This overrides the merge.renormalize configuration variable.

rename-threshold=<n>
Controls the similarity threshold used for rename detection. See also git-diff(1)-M.

subtree[=<path>]
This option is a more advanced form of subtree strategy, where the strategy makes a guess on how two trees must be shifted to match with
each other when merging. Instead, the specified path is prefixed (or stripped from the beginning) to make the shape of two trees to match.

octopus
This resolves cases with more than two heads, but refuses to do a complex merge that needs manual resolution. It is primarily meant to be used
for bundling topic branch heads together. This is the default merge strategy when pulling or merging more than one branch.
ours
This resolves any number of heads, but the resulting tree of the merge is always that of the current branch head, effectively ignoring all
changes from all other branches. It is meant to be used to supersede old development history of side branches. Note that this is different from
the -Xours option to the recursive merge strategy.

subtree
This is a modified recursive strategy. When merging trees A and B, if B corresponds to a subtree of A, B is first adjusted to match the tree
structure of A, instead of reading the trees at the same level. This adjustment is also done to the common ancestor tree.

With the strategies that use 3-way merge (including the default, recursive), if a change is made on both branches, but later reverted on one of the
branches, that change will be present in the merged result; some people find this behavior confusing. It occurs because only the heads and the
merge base are considered when performing a merge, not the individual commits. The merge algorithm therefore considers the reverted change as no
change at all, and substitutes the changed version instead.

NOTES
You should understand the implications of using git rebase on a repository that you share. See also RECOVERING FROM UPSTREAM REBASE below.

When the git-rebase command is run, it will first execute a "pre-rebase" hook if one exists. You can use this hook to do sanity checks and reject
the rebase if it isn’t appropriate. Please see the template pre-rebase hook script for an example.

Upon completion, <branch> will be the current branch.

INTERACTIVE MODE
Rebasing interactively means that you have a chance to edit the commits which are rebased. You can reorder the commits, and you can remove them
(weeding out bad or otherwise unwanted patches).

The interactive mode is meant for this type of workflow:

1. have a wonderful idea

2. hack on the code

3. prepare a series for submission

4. submit

where point 2. consists of several instances of

a) regular use

1. finish something worthy of a commit

2. commit

b) independent fixup

1. realize that something does not work

2. fix that

3. commit it

Sometimes the thing fixed in b.2. cannot be amended to the not-quite perfect commit it fixes, because that commit is buried deeply in a patch
series. That is exactly what interactive rebase is for: use it after plenty of "a"s and "b"s, by rearranging and editing commits, and squashing
multiple commits into one.

Start it with the last commit you want to retain as-is:

git rebase -i <after-this-commit>

An editor will be fired up with all the commits in your current branch (ignoring merge commits), which come after the given commit. You can reorder
the commits in this list to your heart’s content, and you can remove them. The list looks more or less like this:

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

The oneline descriptions are purely for your pleasure; git rebase will not look at them but at the commit names ("deadbee" and "fa1afe1" in this
example), so do not delete or edit the names.

By replacing the command "pick" with the command "edit", you can tell git rebase to stop after applying that commit, so that you can edit the files
and/or the commit message, amend the commit, and continue rebasing.

If you just want to edit the commit message for a commit, replace the command "pick" with the command "reword".

If you want to fold two or more commits into one, replace the command "pick" for the second and subsequent commits with "squash" or "fixup". If the
commits had different authors, the folded commit will be attributed to the author of the first commit. The suggested commit message for the folded
commit is the concatenation of the commit messages of the first commit and of those with the "squash" command, but omits the commit messages of
commits with the "fixup" command.

git rebase will stop when "pick" has been replaced with "edit" or when a command fails due to merge errors. When you are done editing and/or
resolving conflicts you can continue with git rebase --continue.

For example, if you want to reorder the last 5 commits, such that what was HEAD~4 becomes the new HEAD. To achieve that, you would call git rebase
like this:

$ git rebase -i HEAD~5

And move the first patch to the end of the list.

You might want to preserve merges, if you have a history like this:

X
\
A---M---B
/
---o---O---P---Q

Suppose you want to rebase the side branch starting at "A" to "Q". Make sure that the current HEAD is "B", and call

$ git rebase -i -p --onto Q O

Reordering and editing commits usually creates untested intermediate steps. You may want to check that your history editing did not break anything
by running a test, or at least recompiling at intermediate points in history by using the "exec" command (shortcut "x"). You may do so by creating
a todo list like this one:

pick deadbee Implement feature XXX
fixup f1a5c00 Fix to feature XXX
exec make
pick c0ffeee The oneline of the next commit
edit deadbab The oneline of the commit after
exec cd subdir; make test
...

The interactive rebase will stop when a command fails (i.e. exits with non-0 status) to give you an opportunity to fix the problem. You can
continue with git rebase --continue.

The "exec" command launches the command in a shell (the one specified in $SHELL, or the default shell if $SHELL is not set), so you can use shell
features (like "cd", ">", ";" ...). The command is run from the root of the working tree.

$ git rebase -i --exec "make test"

This command lets you check that intermediate commits are compilable. The todo list becomes like that:

pick 5928aea one
exec make test
pick 04d0fda two
exec make test
pick ba46169 three
exec make test
pick f4593f9 four
exec make test
SPLITTING COMMITS
In interactive mode, you can mark commits with the action "edit". However, this does not necessarily mean that git rebase expects the result of
this edit to be exactly one commit. Indeed, you can undo the commit, or you can add other commits. This can be used to split a commit into two:

· Start an interactive rebase with git rebase -i <commit>^, where <commit> is the commit you want to split. In fact, any commit range will do, as
long as it contains that commit.

· Mark the commit you want to split with the action "edit".

· When it comes to editing that commit, execute git reset HEAD^. The effect is that the HEAD is rewound by one, and the index follows suit.
However, the working tree stays the same.

· Now add the changes to the index that you want to have in the first commit. You can use git add (possibly interactively) or git gui (or both)
to do that.

· Commit the now-current index with whatever commit message is appropriate now.

· Repeat the last two steps until your working tree is clean.

· Continue the rebase with git rebase --continue.

If you are not absolutely sure that the intermediate revisions are consistent (they compile, pass the testsuite, etc.) you should use git stash to
stash away the not-yet-committed changes after each commit, test, and amend the commit if fixes are necessary.

RECOVERING FROM UPSTREAM REBASE
Rebasing (or any other form of rewriting) a branch that others have based work on is a bad idea: anyone downstream of it is forced to manually fix
their history. This section explains how to do the fix from the downstream’s point of view. The real fix, however, would be to avoid rebasing the
upstream in the first place.

To illustrate, suppose you are in a situation where someone develops a subsystem branch, and you are working on a topic that is dependent on this
subsystem. You might end up with a history like the following:

o---o---o---o---o---o---o---o---o master
\
o---o---o---o---o subsystem
\
*---*---* topic

If subsystem is rebased against master, the following happens:

o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o' subsystem
\
*---*---* topic

If you now continue development as usual, and eventually merge topic to subsystem, the commits from subsystem will remain duplicated forever:

o---o---o---o---o---o---o---o master
\ \
o---o---o---o---o o'--o'--o'--o'--o'--M subsystem
\ /
*---*---*-..........-*--* topic

Such duplicates are generally frowned upon because they clutter up history, making it harder to follow. To clean things up, you need to transplant
the commits on topic to the new subsystem tip, i.e., rebase topic. This becomes a ripple effect: anyone downstream from topic is forced to rebase
too, and so on!

There are two kinds of fixes, discussed in the following subsections:

Easy case: The changes are literally the same.
This happens if the subsystem rebase was a simple rebase and had no conflicts.

Hard case: The changes are not the same.
This happens if the subsystem rebase had conflicts, or used --interactive to omit, edit, squash, or fixup commits; or if the upstream used one
of commit --amend, reset, or filter-branch.
The easy case
Only works if the changes (patch IDs based on the diff contents) on subsystem are literally the same before and after the rebase subsystem did.

In that case, the fix is easy because git rebase knows to skip changes that are already present in the new upstream. So if you say (assuming you’re
on topic)

$ git rebase subsystem

you will end up with the fixed history

o---o---o---o---o---o---o---o master
\
o'--o'--o'--o'--o' subsystem
\
*---*---* topic

The hard case
Things get more complicated if the subsystem changes do not exactly correspond to the ones before the rebase.

Note
While an "easy case recovery" sometimes appears to be successful even in the hard case, it may have unintended consequences. For example, a
commit that was removed via git rebase --interactive will be resurrected!

The idea is to manually tell git rebase "where the old subsystem ended and your topic began", that is, what the old merge-base between them was.
You will have to find a way to name the last commit of the old subsystem, for example:

· With the subsystem reflog: after git fetch, the old tip of subsystem is at subsystem@{1}. Subsequent fetches will increase the number. (See
git-reflog(1).)

· Relative to the tip of topic: knowing that your topic has three commits, the old tip of subsystem must be topic~3.

You can then transplant the old subsystem..topic to the new tip by saying (for the reflog case, and assuming you are on topic already):

$ git rebase --onto subsystem subsystem@{1}

The ripple effect of a "hard case" recovery is especially bad: everyone downstream from topic will now have to perform a "hard case" recovery too!

BUGS
The todo list presented by --preserve-merges --interactive does not represent the topology of the revision graph. Editing commits and rewording
their commit messages should work fine, but attempts to reorder commits tend to produce counterintuitive results.

For example, an attempt to rearrange

1 --- 2 --- 3 --- 4 --- 5

to

1 --- 2 --- 4 --- 3 --- 5

by moving the "pick 4" line will result in the following history:

3
/
1 --- 2 --- 4 --- 5

GIT
Part of the git(1) suite
NOTES
1. revert-a-faulty-merge How-To
file:///usr/share/doc/git/html/howto/revert-a-faulty-merge.html

Git 1.9.1 12/11/2015 GIT-REBASE(1)
Manual page git-rebase(1) line 583/658 (END) (press h for help or q to quit)
============================================================================================
============================================================================================

posted @ 2021-11-20 15:58  方园FPP  阅读(657)  评论(0编辑  收藏  举报