标签 git 下的文章

git@xxxx访问 git@xxxx访问其实就是使用的ssh服务

搭建步骤:以 root 用户执行,服务器地址 192.168.1.100

#创建git用户
adduser git

#切换到git用户
su git
cd
mkdir .ssh && chmod 700 .ssh
touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys

#创建git仓库
mkdir test.git
cd test.git
git init

#设置git用户的登录密码
passwd
#退出,回到root用户环境
exit

#在客户端创建ssh密匙
ssh-keygen -t rsa
#将对应的公钥添加到服务器git用户ssh认证文件中
ssh-copy-id git@192.168.1.100

#测试能不能访问服务器上的仓库,如果不报错即可访问了
git ls-remote -h git@192.168.1.100:test.git HEAD

#尝试clone仓库到本地
git clone git@192.168.1.100:test.git

应该注意,目前所有这些用户也可以登录服务器并以git用户身份获得 shell 。如果你想限制它,你必须将用户的 shell 更改为git-shell

# 查看现有shell
cat /etc/shells

# 确保在您的系统上安装了git-shell,一般是 /usr/bin/git-shell
which git-shell

# 将上面输出的git-shell的路径添加到/etc/shells最后,保存
sudo -e /etc/shells  

#将git用户的登录shell改成git-shell
sudo chsh git -s $(which git-shell)

现在192.168.1.100将得到这个结果了,这样就不能远程登录了,但是可以正常使用git命令推送和拉取代码,同时也不能使用ssh-copy-id来复制用户公钥,需要手动去服务器上添加

ssh git@192.168.1.100
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
Connection to gitserver closed.

此时,用户仍然可以使用 SSH 端口转发来访问 git 服务器能够访问的任何主机。如果您想防止这种情况发生,您可以编辑该authorized_keys文件并将以下选项添加到您要限制的每个公钥之前:

no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty

结果应如下所示:

cat ~/.ssh/authorized_keys

no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCB007n/ww+ouN4gSLKssMxXnBOvf9LGt4LojG6rs6hPB09j9R/T17/x4lhJA0F3FR1rP6kYBRsWj2aThGw6HXLm9/5zytK6Ztg3RPKK+4kYjh6541NYsnEAZuXz0jTTyAUfrtU3Z5E003C4oxOj6H0rfIF1kKI9MAQLMdpGW1GYEIgS9EzSdfd8AcCIicTDWbqLAcU4UpkaX8KyGlLwsNuuGztobF8m72ALC/nLF6JLtPofwFBlgc+myivO7TCUSBdLQlgMVOFq1I2uPWQOkOWQAHukEOmfjy2jctxSDBQ220ymjaNsHT4kgtZg2AYYgPqdAv8JggJICUvax2T9va5 gsg-keypair

no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEwENNMomTboYI+LJieaAY16qiXiH3wuvENhBG...

现在 Git 网络命令仍然可以正常工作,但用户将无法获得 shell。正如输出所述,您还可以在git用户的主目录中设置一个目录,git-shell以稍微自定义命令。例如,您可以限制服务器将接受的 Git 命令,或者您可以自定义用户在尝试 SSH 时看到的消息。运行git help shell以获取有关自定义 shell 的更多信息。

实现HTTP访问
apache 实现
让我们来看看一个非常基本的设置。我们将使用 Apache 作为 CGI 服务器进行设置。如果您没有 Apache 设置,您可以在 Linux 机器上使用以下内容进行设置:

sudo apt-get install apache2 apache2-utils
a2enmod cgi alias env

这也使得mod_cgi,mod_alias和mod_env模块,这些都需要这正常工作。

将仓库存放的目录(以/srv/git为例)的用户组设置为 www-data以便 Web 服务器可以读取和写入访问存储库,因为运行 CGI 脚本的 Apache 实例(默认情况下)将作为该用户运行:

chgrp -R www-data /srv/git

接下来,我们需要向 Apache 配置添加一些内容,以将其git-http-backend作为处理程序运行,以处理进入/gitWeb 服务器路径的任何内容。

SetEnv GIT_PROJECT_ROOT /srv/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/

如果您省略GIT_HTTP_EXPORT_ALL环境变量,那么 Git 将只为未经身份验证的客户端提供包含git-daemon-export-ok文件的存储库,就像 Git 守护程序(git-daemon-export-ok)所做的那样。

最后,您将要告诉 Apache 允许请求git-http-backend并以某种方式对写入进行身份验证,可能使用像这样的 Auth 块:

<Files "git-http-backend">
    AuthType Basic
    AuthName "Git Access"
    AuthUserFile /srv/git/.htpasswd
    Require expr !(%{QUERY_STRING} -strmatch '*service=git-receive-pack*' || %{REQUEST_URI} =~ m#/git-receive-pack$#)
    Require valid-user
</Files>

这将要求您创建一个.htpasswd包含所有有效用户密码的文件。以下是将“schacon”用户添加到文件的示例:

$ htpasswd -c /srv/git/.htpasswd schacon

有很多方法可以让 Apache 对用户进行身份验证,您必须选择并实现其中之一。这只是我们能想到的最简单的例子。您几乎肯定还想通过 SSL 进行设置,以便对所有这些数据进行加密。

我不想在 Apache 配置细节讲太多,因为您很可能使用不同的服务器或有不同的身份验证需求。
这里只是说明 Git 带有一个 CGI 处理程序 git-http-backend,当调用它时将完成所有协商以通过 HTTP 发送和接收数据。
它本身不实现任何身份验证,但可以在调用它的 Web 服务器层轻松控制。
您几乎可以使用任何支持 CGI 的 Web 服务器来执行此操作,因此请选择您最了解的服务器。

有关在 Apache 中配置身份验证的更多信息,请在此处查看 Apache 文档:https://httpd.apache.org/docs/current/howto/auth.html

nginx实现
nginx配置

# 配置以 /git 开始的虚拟目录
server {
    listen               80;
    server_name          git.example.com;

    auth_basic           "Git Access";
    auth_basic_user_file /etc/nginx/.htpasswd_git;
    error_log            /var/log/nginx-git-error.log;
    access_log           /var/log/nginx-git-access.log;
    client_max_body_size 0;

    root /srv/git/;

    location ~ /git(/.*) {

        fastcgi_pass  unix:/var/run/fcgiwrap.socket;
        include       fastcgi_params;
        fastcgi_param SCRIPT_FILENAME     /usr/libexec/git-core/git-http-backend;
        fastcgi_param GIT_PROJECT_ROOT    /srv/git;
        fastcgi_param REMOTE_USER         $remote_user;
        fastcgi_param PATH_INFO           $1;
        fastcgi_read_timeout              600;
        client_max_body_size 100M;
    }
}

参考 nginx ngx http auth basic module , 用户认证文件格式如下:
/etc/nginx/.htpasswd_git

# comment
name1:password1
name2:password2:comment
name3:password3

可以使用 htpasswd 命令创建用户, 如果服务器上没有这个命令的话, 可以输入命令 apt-get install apache2-utils 来安装这个命令, 安装了这个命令之后, 就可以使用它来创建认证用户了, 比如要创建用户 user1, 输入命令如下:

htpasswd /etc/nginx/.htpasswd_git user1

支持以下密码类型:
使用 crypt() 函数加密; 可以使用 Apache HTTP Server 发行版中的“htpasswd”实用程序或“openssl passwd”命令生成;
使用基于 MD5 的密码算法 (apr1) 的 Apache 变体进行散列; 可以使用相同的工具生成;
由 RFC 2307 中描述的“{scheme}data”语法(1.0.3+)指定; 当前实现的方案包括 PLAIN(一个示例,不应使用)、SHA(1.3.13)(不应使用纯 SHA-1 散列)和 SSHA(一些软件包使用的加盐 SHA-1 散列,特别是 OpenLDAP 和 Dovecot)。

创建 git 代码库
上面配置的 git 跟目录是 /srv/git , 我们在这个目录下初始化一个空的代码库, 命令如下:

cd /srv/git
git init --bare test.git
将test.git用户和用户组设置为nginx进程可以读写的用户

重启 nginx 并测试
输入命令重启 nginx 并测试 git 服务:

nginx -s reload
git clone https://192.168.1.100/git/test.git

问题
来自这个网友遇到的问题:https://stackoverflow.com/questions/58437697/multiple-simultaneous-requests-with-git-http-backend-on-nginx-fastcgi-proxy
未经验证:
从测试来看,如果一次有多个请求,代理将失败(代码为 504)
它为每个新的 http 请求生成一个新的 git-http-backend 实例。编译它(需要安装 go 语言)通过

go build git-http-multi-backend.go

并运行它

./git-http-multi-backend -r /Path/To/Repos

这将使它监听 :80(端口可以更改)。您现在只需将 nginx 配置更改为类似

location ~ /git(/.*) {
    proxy_pass http://localhost:80;
}

这不是最优雅的解决方案,因为完全可以通过摆弄 nginx 配置来实现相同的效果。
git-http-multi-backend 工具的作者甚至谈到了它。

您需要增加可以生成的 FCGI_CHILDREN 的最大数量。就我而言,我编辑了 /etc/init.d/fcgiwrap 并将 FCGI_CHILDREN 设置为例如 3。现在,我可以一次检出/克隆/推送 3 个存储库。
哦顺便说一句:虽然编辑这个脚本可能被认为不是一个好习惯。我只是想,将脚本放入 /etc/default/fcgiwrap 并使用FCGI_CHILDREN=3也可以完成这项工作,并且单独保留启动脚本

总结:

  1. rebase 可以尽可能保持 master 分支干净整洁,并且易于识别 author
  2. squash 也可以保持 master 分支干净,但是 master 中 author 都是 maintainer,而不是原 owner
  3. merge 不能保持 master 分支干净,但是保持了所有的 commit history,大多数情况下都是不好的,个别情况挺好

squash 使用:squash merge
在使用 git 的过程中,可能你遇到过想要合并多个 commit 为一个,然后很多人会告诉你用 git commit --amend,然后你发现里面有你的多个 commit 历史,你可以通过 pick 选择,squash 合并等等。同样得,merge 的时候也可以这么干,你只需要这么简单的两步:

  • 切换到目标分支:git checkout master
  • 以 squash 的形式 merge:git merge --squash devel

你会发现,在 master 分支上居然有未提交的修改,然后你就需要在 master 上主动提交了修改,注意,这里是你 commit 的,也就是改变了 commit 的 author。

rebase 使用
但是,作为处女座的程序员肯定是不能忍受目前的情况的,因为我们既想合并 commits,又想保留作者的信息,那么有没有什么好办法呢?肯定是有的啦,这个时候我们可以尝试一下 rebase,操作步骤是这样的:

  • 先切换到 devel 分支(不一样咯):git checkout devel
  • 变基:git rebase -i master
  • 切换回目标分支:git checkout master
  • 合并: git merge devel

这里完成了第二步之后我想你应该大概知道发生了什么事了,我们在 devel 里面对照 master 进行了变基,所谓的变基其实就是找到两个分支共同的祖先,然后在当前分支上合并从共同祖先到现在的所有 commit,所以我们在第二步的时候会选择怎么处理这些 commit,然后我们就得到了一个从公共commit 到现在的单个 commit,这个时候别人讲我们这个 commit 合并到 master 也只会在 master 上留下一个 commit 记录,就像这样:

虽然这个 commit history 线看上去很不错,而且也比较符合实际情况,但是我们需要注意到的有点就是分支上的开发者需要自己执行变基操作,从而导致他的原始 commit history 变化了(可以理解成被合并了)。

原文:
https://www.jianshu.com/p/684a8ae9dcf1

git reset --hard和git clean -f是一对好基友
结合使用他们能让你的工作目录完全回退到最近一次commit的时候

git clean 从工作目录删除所有没有tracked过的文件

reset只影响被track过的文件, 所以需要clean来删除没有track过的文件
结合使用这两个命令能让你的工作目录完全回到一个指定的的状态

用法

git clean -n

是一次clean的演习, 告诉你哪些文件会被删除. 记住他不会真正的删除文件, 只是一个提醒

git clean -f

删除当前目录下所有没有track过的文件. 他不会删除.gitignore文件里面指定的文件夹和文件, 不管这些文件有没有被track过

git clean -f

删除指定路径下的没有被track过的文件

git clean -df

删除当前目录下没有被track过的文件和文件夹

git clean -xf

删除当前目录下所有没有track过的文件. 不管他是否是.gitignore文件里面指定的文件夹和文件

git clean对于刚编译过的项目也非常有用.
能轻易删除掉编译后生成的.o和.exe等文件.
这个在打包要发布一个release的时候非常有用

下面的例子要删除所有工作目录下面的修改, 包括新添加的文件. 假设你已经提交了一些快照了, 而且做了一些新的开发

git reset --hard
git clean -df

自摘: 林德熙博客 http://blog.csdn.net/lindexi_gd

在合并pull两个不同的项目,会出现的问题: refusing to merge unrelated histories

先pull,因为两个仓库不同,发现refusing to merge unrelated histories

无法pull

因为他们是两个不同的项目,要把两个不同的项目合并,git需要添加一句代码,在git pull,这句代码是在git 2.9.2版本发生的,最新的版本需要添加--allow-unrelated-histories

假如我们的源是origin,分支是master,那么我们 需要这样写

git pull origin master --allow-unrelated-histories

需要知道,我们的源可以是本地的路径