Linux命令 git


原文链接: Linux命令 git

[](https://github.com/brigade/overcommit)

Git补丁管理(方便在多台机器上开发同步时用)

git diff > ../sync.patch         # 生成补丁
git apply ../sync.patch          # 打补丁
git apply --check ../sync.patch  # 测试补丁能否成功

高富帅们的Git技巧 - 新闻 - SegmentFault

解决 How do I remove files saying “old mode 100755 new mode 100644” from unstaged changes in Git?

git config core.filemode false
这种情况一般出现在Windows和Linux时,属于项目本身配置的问题,所以把filemode检查关闭就可以了

git如何忽略已经提交的文件

git update-index --assume-unchanged /path/to/file

git代理设置方法解决

git config --global https.proxy http://127.0.0.1:1080
git config --global https.proxy https://127.0.0.1:1080
git config --global --unset http.proxy
git config --global --unset https.proxy
npm config delete proxy
git config --global http.proxy 'socks5://127.0.0.1:1080'
git config --global https.proxy 'socks5://127.0.0.1:1080'

如何解决 fatal: Authentication failed for又不弹出用户名和密码 解决办法

git.exe fetch -v --progress "origin"
fatal: Authentication failed for 'https://gitee.com/qssq666/xxxxxx.git/'
解决方法如下:
git config --system --unset credential.helper

然后就终于可以重新填写用户名和密码进行提交了。

该问题已解决。
原因是:git config --global credential.helper store 该命令可以将用户名和密码长期全局地长期地存储在客户端(实际是客户端所在电脑,并非git的任何目录下,也就是说,即使重装git,改密码也存在。)。因为,这里保存的账号和密码会自动应用到每一个git clone指令,如果想要克隆的不是该账号下的项目,就只会得到403错误。
解决办法:
方法一:
增加远程地址的时候带上密码也是可以的。(推荐)
http://yourname:password@git.oschina.net/name/project.git
方法二:
运行命令:rm ~/.git-credentials,删掉 git config --global credential.helper store 保存的账号和密码。回到每次输入用户名和密码。

为此写了博客http://www.cnblogs.com/jarvisjin/p/5915419.html

解决合并错误

git checkout master .drone.yaml

让 git 公私分明

  作为开源爱好者,我们会大量使用开源代码构建项目,开源自己的代码。同时我们也会受雇于商业公司,为公司开发商业程序。显然的,我们应该公私分明,在商业项目和开源项目中使用不同的用户名和邮箱。最粗笨的方法就是在每个项目代码仓库当中修改配置。但是这样做太过繁琐,我们需要个更简单的方法——让 git 公私分明,自动的帮我们在不同分组的项目使用不同的配置。

  使用 conditional configuration includes 可以轻松解决这一问题。首先,需要确定你的 git 版本不低于 2.13,否则需要升级 git 到新版本。
fengmomuwei:~$git version
git version 2.14.1

  接着,你需要把代码分组放置在不同的目录下。例如,开源代码放置在 opensource 目录,商业代码放置在 company 目录。opensource 目录的代码使用默认的全局配置,company 目录的代码使用单独的用户名和邮箱。当然,如果之前你的代码已经是类似分组的状态,那就直接下一步吧。

fengmomuwei:projects$ls
company opensource

  做好准备工作,那我们可以开始修改配置了。使用 git config --global --edit 修改 git 全局配置文件,在末尾添加下列配置:

[includeIf "gitdir:/company/"]

path = ~/.gitconfig.company

  使用上述配置执行 git 命令时,如果目录当中能够匹配到 /company/ 路径,则加载 ~/.gitconfig.company 文件覆盖全局配置中对应的字段。我们为 company 目录当中的代码设置不同的用户名和邮箱,只需要编辑 ~/.gitconfig.company 添加下述配置即可:
[user]
name = Yourname
email = Yourname@company.com

  当然,你还可以为 company 目录设定其它的专属配置。自此,我们不必再一个个的在不同的代码仓库中修改配置。尽情享受工作与开源的乐趣吧!

git 查看某个文件的修改历史

  1. git log -p filename

查看文件的每一个详细的历史修改,如果没有-p选项,只显示提交记录,不显示文件内容修改,git log -p -3 filename 显示最近的3次提交。

  1. git log --pretty=oneline filename

每一行显示一个提交,先显示哈希码,再显示提交说明。

  1. git blame filename

查看文件的每一行是哪个提交最后修改的。

git找到两个分支的分叉点

https://stackoverflow.com/questions/1527234/finding-a-branch-point-with-git#4991675
git rev-list --boundary develop...master | grep "^-" | cut -c2-
git rev-list ^develop --first-parent master

默认使用 rebase

git config --global branch.autosetuprebase always

对比指定目录与上次提交之间的差别(或者更准确的 说是在当前分支)。

git diff HEAD -- ./lib

恢复指定目录文件

git checkout HEAD~ application/admin/

把hello.rb从HEAD中签出并且把它恢复成未修改时的样子.

git checkout -- hello.rb
红色 绿色 白色

                   Index                     HEAD remote repo

working staging local repo
工作区 暂存区 本地仓库

   git add           =>        git commit       =>   

<= git reset --soft <= git rm --cached <=
<= git reset
<= git checkout

当我们需要删除暂存区或分支上的文件, 同时工作区也不需要这个文件了, 可以使用
git rm file_path 同时删除 staging staging
当我们需要删除暂存区或分支上的文件, 但本地又需要使用, 只是不希望这个文件被版本控制, 可以使用
git rm --cached file_path 仅删除staging 保留staging

git rm -r --cached .

git清理大文件

使用git branch-filter来遍历git history tree, 可以永久删除history中的大文件,达到让.git文件瘦身的目的。

下面给出步骤(以下步骤非常危险,操作需谨慎!别把公司删没了哈哈)

  1. 首先找出git中前五大的文件:

git verify-pack -v .git/objects/pack/pack-*.idx | sort -k 3 -g | tail -5

  1. 根据文件id找出对应的文件名:

git rev-list --objects --all | grep 8f10eff91bb6aa2de1f5d096ee2e1687b0eab007

  1. 彻底删除大文件

    git filter-branch --index-filter 'git rm --cached --ignore-unmatch <your-file-name>'
    rm -rf .git/refs/original/
    git reflog expire --expire=now --all
    git fsck --full --unreachable
    git repack -A -d
    git gc --aggressive --prune=now
    git push --force [remote] master
    

    首先,里面最重要的两条命令是 git filter-branch 和 gc, filter-branch 真正在清理,但是只运行它也是没用的,需要再删除备份的文件,重新打包之类的,最后的gc命令,

    用来收集产生的垃圾,最终清除大文件。

    一步到位,再看看你的.git文件,有没有大吃一惊呢!

    3.5 git给远程库添加多个url地址

    场合:你可能想要把你的本地的git库,既push到github上,又push到开源中国的Git@OSC上或者coding net上,怎么解决呢?有人可能会用两个甚至多个远程库,即再添加一个远程库git remote add origin2;这个方法很低效,因为你要git push 两次才能完成push到两个库。
    解答原理:git的一个远程库可以对应多个地址。
    基本命令:

    	git remote add gh-pages git@github.com:rinetd/rinetd.github.io
    	git remote set-url --add --push gh-pages git@github.com:rinetd/rinetd.github.io
    	git remote set-url --add --push gh-pages git@gitlab.com:rinetd/rinetd.gitlab.io.git
    
    	git remote add origin git@github.com:rinetd/drone-rsync
    	git remote set-url --add --push origin git@github.com:rinetd/drone-rsync
    	git remote set-url --add --push origin git@pytool.pytool.com:pytool/drone-rsync.git
    
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
[remote "origin"]
	url = git@github.com:rinetd/functools.git
	fetch = +refs/heads/*:refs/remotes/origin/*
	pushurl = git@github.com:rinetd/functools.git
	pushurl = git@pytool.github.com:pytool/functools.git
[branch "master"]
	remote = origin
	merge = refs/heads/master
	rebase = true

在本地仓库创建一个指向远程仓库url的链接别名name,可以任意命名:git remote add name url1 (name可以为origin、both等等自定义的名字)

  1. 增加第1个远程库地址:git remote set-url --add --push origin url1 #remote url1 必须添加 否则无法推送到真正的主库
  2. 再增加第2个远程库地址:git remote set-url --add --push origin url2
  3. 删除url链接别名name:git remote rm name (常见的为origin)
    显示当前所有远程库的详细信息,显示格式为:远程库名字 url连接(类型),命令:git remote -v
    查看config文件,里面可以看到添加的地址,位于当前工程.git/config中,可使用命令:git config -e
    推送时只需要执行命令:git push name master,其中name就是url的链接别名,master是推送的分支,要保证几个推送仓库的分支命名是一样的。

3.6 查看改动的内容
改动的内容如果commit的话,可使用:
git log -n 2 --stat :查看最后两次改动过的文件
git log -n 1 -p :查看最后一次提交更改的细节
使用git diff来查看改动内容,其中HEAD代表commit版本,Index代表staged版本
git diff:比较工作目录(Working tree)和暂存区域快照(index)之间的差异,也就是修改之后还没有暂存起来的变化内容。
git diff --cached:查看已经暂存起来的文件(staged)和上次提交时的快照之间(HEAD)的差异
git diff --staged:显示的是下一次commit时会提交到HEAD的内容
git diff HEAD:查看workspace和local repository的差别
git diff b1 b2 或 git diff b1..b2:将b1和b2分支上的最新提交做diff
git diff test:查看当前目录和test分支的差别
git diff HEAD^ HEAD:比较上次提交commit和上上次提交
git_diff_pic

3.7 分支重命名
步骤如下:

把test1分支重命名为test2:git branch -m test1 test2
删除远程分支test1:git push --delete origin test1
将本地分支test2推到远程:git push origin test2

清理 .git 缩减目录大小

git gc

Git合并branch上的指定文件

git checkout -p develop A.h //不切换 branch,把 develop 上的A.h更新到当前分支
git checkout develop .drone* //去掉-p参数,新增 .drone.yml .drone.yml.sig 文件

允许空提交

git commit --allow-empty -m "Initializing gh-pages branch"

lfs

Apt/deb repos: curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
Yum/rpm repos: curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.rpm.sh | sudo bash
sudo apt-get install git-lfs

github Emoji表情包

http://www.webpagefx.com/tools/emoji-cheat-sheet/

关闭git pull 弹出的merge 信息

git reset --hard origin/master

[core]
    mergeoptions = --no-edit

git config --global core.mergeoptions --no-edit

git clone文件太大时怎样处理

clone的时候,可以指定深度,如下,为1即表示只克隆最近一次commit.
git clone --depth 1 git@github.com:/

subtree 在主分支管理子项目

1、初始化子项目Subtree
通过
cd P1项目的路径
git subtree add --prefix=用来放S项目的相对路径 git地址 xxx分支
这样的命令,把S项目(我们姑且叫他S项目)的代码下载到--prefix所指定的目录——我们姑且叫他S目录把,并在P1项目里自动产生一个commit(就是把S目录的内容提交到P1项目里)。
对于P2项目也做同样的操作
2、像往常一样更新代码
大家在P1项目里各种提交commit,其中有些commit会涉及到S目录的更改,正如前面提到的,这是没任何关系的,大家也不会感受到有任何不一样。
3、提交更改到子项目的Git服务器
关键的地方来了:
当维护这个S项目 Subtree 的人希望把最近这段时间对S目录的更改提交到S项目的 Git 服务器上时,他执行一段类似于这样的命令:
cd P1项目的路径
git subtree push --prefix=S项目的路径 git地址 xxx分支
Git 会遍历所有的commit,从中找出针对S目录的更改,然后把这些更改记录提交到S项目的Git服务器上
4、更新子项目新的代码到父项目
OK,现在S项目有大量的新代码了,P2项目也想使用这些新代码,维护P2这个Subtree的人只要执行:
git subtree pull --prefix=S项目的路径 git地址 xxx分支
这样就可以将P2项目里S项目目录里的内容更新为S项目xxx分支的最新代码了。

Git多账号切换

有时候会遇到需要使用多个git账号的情况,手动切换是在过于麻烦。
于是就有了一下的解决方案:
首先,切换到ssh的key目录下:
cd ~/.ssh
然后使用ssh-keygen命令创建一个新的SSH key:
ssh-keygen -t rsa -C "sencond@mail.com" -f id_rsa_second
其中id_rsa_second表示保存的key的名称,可以自定义,命令执行之后会在.ssh目录里出现两个文件其中id_rsa_second.pub表示公钥。后面会用到。
由于默认情况下,每次进行SSH连接时默认发送本地钥匙(默认为~/.ssh/id_rsa)。所以之前生成的id_rsa_second在默认情况下是没有被用到的。
这时就需要在~/.ssh 目录创建config文件,该文件用于配置钥匙对应的服务器信息。具体语法如下:
Host 别名

HostName        主机名
Port            端口
User            用户名
IdentityFile    密钥文件的路径

其中Host别名自己任意给出,能方便记忆就行。给出一个示例配置以供参考:

Default github user(first@mail.com)

Host github.com

 HostName github.com
 User git
 IdentityFile ~/.ssh/id_rsa

second user(second@mail.com)

Host github-second

 HostName github.com
 User git
 IdentityFile ~/.ssh/id_rsa_second

配置完成之后,在连接非默认账号需要修改一下远程库的地址,
如本来的远程库地址为git@github:sencond/test.git
现在就需要改为git@github-second:sencond/test.git。
而且通过 ssh + 别名就能登录远程库
注意:

切换账号的时候要修改相应的配置文件
 git config --global user.name 用户名
 git config --global user.email second@email.com
在远程端添加前面生成的id_rsa_second.pub的公钥到远程库里。
使用对应的ssh key密码。
`