Git 使用杂项

2015-09-10 Thursday     linux , misc

记录 git 常见的示例,可以用来作为参考使用。

TAG 管理

一般可以通过 git describe 显示离当前提交最近的 TAG 信息,如果最近有提交为 TAG,则只显示 TAG 信息,否则会有相关的后缀来描述该 TAG 后有多少次提交,以及最新的 CommitID 。

v1.0.0-rc1-10-g0c2b1cf
  v1.0.0-rc 表示TAG的信息
  10 表示自从打了v1.0.0-rc1之后又有10提交
  g0c2b1cf g为git缩写,用于区分多个版本管理工具;0c2b1cf表示最新提交的CommitID

当知道了该信息后,如果要检查某个版本的问题,可以直接通过 git checkout 0c2b1cf 切换到对应的代码。

多分支管理

首先,TAG 信息是全局的,但是不同的分支可以分别通过 git describe 显示版本信息。例如,在开源开发时有内部版本和开源版本,那么就可以通两个分支进行管理,分别打 TAG 信息。

$ git init
$ echo "Version 1" > README.md
$ git add -A .
$ git commit -m "Version 1.0"
$ git tag -a v1.0 -m 'Version 1.0'

$ git checkout -b master-os
$ echo "Version 2" > README.md
$ git add -A .
$ git commit -m "Version 2.0"
$ git tag -a v2.0 -m 'Version 2.0'

$ git describe --match "v[0-9]*" --abbrev=5 HEAD 2>/dev/null

其它

注意,如果要使用 describe 功能,需要使用 Annotated Tags ,否则会报错,命令行中可以通过如下命令执行。

$ git tag -a v1.4 -m "version 1.4"

免登陆

对于不同的 git 版本,可以有如下的几种设置方式。

http

v1.7.9 later

git-v1.7.9 之后的版本,对于 HTTP(S) 链接方式,可以通过 Credential Helpers 实现免登陆,可以通过如下方式配置。

----- 直接缓存在内存中
$ git config --global credential.helper cache

----- 默认过期时间为15min,可以通过如下方式设置为1hour
$ git config --global credential.helper "cache --timeout=3600"

除了 cache 之外,还可以用各个平台上的 keyring 工具,例如 MacOS (osxkeychain)、Windows (wincred)、Linux (gnome-keyring) 等。

v1.7.9 before

对于 v1.7.9 之前版本,可以设置配置文件中的 origin URL,将其配置为如下内容。

https://you:password@github.com/you/example.git

当然,也可以通过如下命令进行配置。

$ git config remote.origin.url https://you:password@github.com/you/example.git

不过这种方式的 密码是明文保存的,其安全性显而易见。

netrc

这个是通用的方式,不过也是明文保存密码。

$ chmod 600 ~/.netrc
$ cat ~/.netrc
machine <hostname> login <username> password <password>

对于 Windows 则文件要命名为 _netrc,同时设置好 %HOME% 环境变量。

ssh

首先设置全局配置。

$ git config --global user.name "foobar hello"
$ git config --global user.email "foobar@kidding.com"

SSH 模式免登陆配置

注意: 一定要保护好私钥文件

$ ssh-keygen -t rsa -N "" -f ~/.ssh/git_id -C "foobar@example.com"
$ cat << EOF >> ~/.ssh/config
# 添加的是git@之后的域名
Host gitlab.com
    User foobar
    Identityfile ~/.ssh/git_id
EOF

然后在 gitlab 的个人 Profile 中,也就是 Profile Setting=>SSH Kyes,添加上述生成的公钥,通过如下方式测试。

$ ssh -T git@gitlab.com
Welcome to GitLab, foobar hello!

如果使用非标准 22 端口,那么需要通过 -p PORT 参数指定,而非使用 your.host.com:PORT 这种方式。

注意:配置文件中同样也需要通过 Port PORT 参数指定。

修改已提交 commit

经常会遇到一些不希望的提交,例如误添加了密码,所以就会有增删改某次或某些提交的需求,这里简单收集下修改本地和远程版本历史的一些方法。

其它

修改远端地址

主要所有如下几种方法。

----- 0. 查看当前的远端设置
$ git remote -v

----- 1. 直接修改配置
$ git remote set-url origin [URL]
----- 2. 删除后再重新添加
$ git remote rm origin
$ git remote add origin [URL]

常用命令

----- 配置用户名密码
$ git config --global user.name  "Your Name"
$ git config --global user.email "yourname@example.com"
$ git config --list

----- 如果不关心文件权限等,如Windows中
$ git config core.filemode false

----- 初始化或者clone一个库
$ git init
$ git clone https://github.com/user/repository.git
$ git help clone

----- 从远端更新,origin指定远端库,master为远端分支
$ git pull origin master              ← 等价于fetch+merge
$ git fetch origin master             ← 只获取远程分支
$ git merge origin master             ← 手动合并

----- 查看远端服务器,修改origin,以及添加remote分支
$ git remote -v
$ git remote set-url origin http//github.com/repo.git
$ git remote add remote-name https://github.com/user/repo.git

----- 查看提交的差异内容
$ git diff                                               ← 未添加到staged的提交
$ git diff --cached                                      ← 已经staged但是未commited的提交
$ git diff origin/master                                 ← 本地修改与远端master的差异
$ git diff COMMIT1_ID COMMIT2_ID                         ← 两次提交的修改
$ git diff --name-only COMMIT1_ID COMMIT2_ID             ← 只查看修改的文件
$ git diff-tree --no-commit-id --name-only -r COMMIT_ID  ← 某次提交的修改
$ git show --pretty="format:" --name-only COMMIT_ID      ← 同上
$ git show COMMIT_ID                                     ← 查看详细细节

----- 当前的状态,然后添加到staged,并提交
$ git status
$ git add changed_file.txt
$ git add folder-with-changed-files/
$ git commit -m "Commiting changes"

----- 重命名或者删除一些文件
$ git rm removeme.txt tmp/crap.txt
$ git mv file_oldname.txt file_newname.txt
$ git commit -m "deleting 2 files, renaming 1"

----- 修改最近一次提交的提交信息,并提交到远端
$ git commit --amend -m "New commit message"
$ git push origin master

----- 查看日志
$ git log                                                ← 最近的提交日志
$ git log -2                                             ← 最近的两个提交日志
$ git log -p -2                                          ← 查看最近两次的详细日志
$ git log --pretty=oneline                               ← 单行打印

----- 通过一次提交回退一次提交,会保存一次新的commit
$ git revert dd61ab21
----- 取消一次提交
$ git reset --soft  HEAD~1                               ← 删除上次commit,文件回退到stage
$ git reset --soft  HEAD@{1}
$ git reset --mixed HEAD~1                               ← (默认)删除上次commit,文件回退到工作区
$ git reset --hard  HEAD~1                               ← 彻底回到上次commit,文件回被删除
$ git reset 56e05fced
$ git reset origin/master                                ← 取消本地未提交的内容
$ git fetch origin                                       ← 或者直接获取远端的内容
$ git reset --hard origin/master                         ← 接上

----- 插件本地分支以及所有分支
$ git branch
$ git branch -a

----- 生成patch文件
$ git diff > patch-issue-1.patch                         ← 做些修改,创建patch
$ git add newfile                                        ← 新建文件并创建patch
$ git diff --staged > patch-issue-2.patch                ← 接上
$ git add newfile                                        ← 添加新文件,做些修改并创建一个patch
$ git diff HEAD > patch-issue-2.patch                    ← 接上
$ git format-patch COMMIT_ID                             ← 为某个commit生成patch
$ git format-patch HEAD~2                                ← 最近两次提交生成patch
$ git format-patch origin/master                         ← 为所有未提交内容生成patch
$ git format-patch --binary --full-index origin/master   ← 创建包含二进制文件的patch
$ git apply -v patch-name.patch                          ← 应用patch
$ git am patch1.patch                                    ← 应用通过format-patch生成的patch

----- 获取最近一次提交的完整CommitID以及短ID
$ git rev-parse HEAD
$ git rev-parse --short HEAD

----- 本地分支重命名(还没有推送到远程)
$ git branch -m oldName newName

----- 远程分支重命名(已经推送远程-假设本地分支和远程对应分支名称相同)
--- A. 重命名远程分支对应的本地分支
$ git branch -m oldName newName
--- B. 删除远程分支
$ git push --delete origin oldName
--- C. 上传新命名的本地分支
$ git push origin newName
--- D. 把修改后的本地分支与远程分支关联
$ git branch --set-upstream-to origin/newName

----- 替换已经存在的远端仓库,也就是报remote origin already exists
----- 1. 首先删除origin的远程仓库
$ git remote rm origin
----- 2. 再添加远程git仓库
$ git remote add origin git@github.com:FBing/java-code-generator
$ git push -u origin --all
$ git push -u origin --tags

常见错误

记录日常遇到的错误异常。

Certificate Issuer

完整的报错是 Peer's Certificate issuer is not recognized. ,主要是由于 HTTPS 的证书无法识别导致,可以将无法识别的证书添加到根证书,或者直接忽略。

这里简单使用后者。

----- 可以通过环境变量设置忽略SSL校验
$ echo 'export GIT_SSL_NO_VERIFY=true' >> ~/.bashrc
$ source ~/.bashrc

----- 也可以在git中进行配置
$ git config http.sslVerify "false"
$ git config --global http.sslVerify false
$ git config http.sslCAinfo /your/path/to/cacert-client.pem

Push.default

对于 2.0 以后的版本,默认安装之后会有如下的警告信息。

warning: push.default is unset; its implicit value is changing in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the current behavior after the default changes, use:

  git config --global push.default matching

To squelch this message and adopt the new behavior now, use:

  git config --global push.default simple

See 'git help config' and search for 'push.default' for further information.
(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode
'current' instead of 'simple' if you sometimes use older versions of Git)

在 git 中 push 代码时,会有些固定的策略:

  • nothing 什么都不干 (要它干嘛! 测试用的?)。
  • matching 本地所有的分支都push上去。
  • upstream 当本地分支有upstream (也就是有对应的远程分支) 时 Push 到对应的远程分支。
  • simple 和 upstream 一样,但不允许将本地分支提交到远程不一样名字的分支。
  • current 把当前的分支 push 到远程的同名分支.

git 1.x 的默认策略是 matching,在 git 2.0 之后 simple 会成为新的默认策略。

matching 不友好之处在于,我们大部分情况都是同步本地的当前分支到远程,如果本地有二三十个分支,那么就会看到大量的刷屏,而且如果其它分支也有更新的话就可能会出现大量的 push fail 信息。

相比来说,simple 这个选项是非常安全的选项,至少能阻止新手误操作覆盖远程分支,所以 git 会在 2.0 时将其作为默认策略。但是需要保证远程与本地的分支名称相同。

大部分情况想要做的只是 push 当前的分支,那么最适合的就是 upstream 。

可以通过如下方式查看、修改全局的配置,相关的配置文件保存在 ~/.gitconfig 中。

$ git config --global --list
$ git config --global push.default upstream

agent refused operation

完整的报错如下。

sign_and_send_pubkey: signing failed: agent refused operation

一般是在服务器添加完公钥后报错,可以通过执行如下命令方式解决。

$ eval "$(ssh-agent -s)"
$ ssh-add

参考

git - 简明指南,一些常见的使用命令。

Git 工具 - 重写历史 很不错的介绍如何重写历史的工具。



如果喜欢这里的文章,而且又不差钱的话,欢迎打赏个早餐 ^_^


About This Blog

Recent Posts

Categories

Related Links

  • RTEMS
    RTEMS
  • GNU
  • Linux Kernel
  • Arduino

Search


This Site was built by Jin Yang, generated with Jekyll, and hosted on GitHub Pages
©2013-2019 – Jin Yang