background

If you are curious about the principle behind the github platform, let’s explore and develop our own Github

There are several open source projects on the market where we can deploy private Git services

project Development of language address
gitlab ruby Gitlab.com/gitlab-org/…
gogs go github.com/gogs/gogs
gitea go Github.com/go-gitea/gi…

Here are some of the problems I encountered while building a private Git service using these projects

  • Gitlab has certain performance requirements for machines like raspberry pie (My 4 b / 4 g) This system often freezes after installation. Please refer to the installation requirements for details:Docs. Gitlab. Cn/jh/install /…
  • Gogs running does not have high requirements on machine performance, but it is developed based on GO language. As a front-end developer, it is not conducive to secondary function expansion
  • Gitea is based on goGS

project

In line with the spirit of technical exploration and the enthusiasm of repeating the wheel, so set out to build a front-end developer friendly Git code management platform [Heart code]

Open source: github.com/lzuntalente… Example site: git.lzz.show/lz/lz-git

The principle of plane analysis

In fact, the essence of these platforms is to execute git commands remotely. When we operate on a page or execute git commands locally, we send a request to a remote server and attach the request content. These platforms help us execute git commands on the server

For example, when we create a project on the page, we are actually executing git init on the server

If you have Git installed, run the git clone dir command to clone a repository and run all git commands in the dir directory

implementation

technology

Lerna front-end: Typescript + React + ANTD back-end: Nestjs + mysql

The project architecture

Create a project

Git init –bare blog. Git init –bare blog. Git does not need to store a working directory on the server. Create an empty repository with –bare (red box at the top of the image below). When you clone a project, you will have an extra directory in your local directory

You can see that we have added.git to the name of the repository, which means that it is a git repository. As you can see when you clone a project from GitHub, they also provide a clone address with.git, so that it is the same

Pull and push code

Since it is not possible to clone dir on a remote server, we use HTTP mode for cloning

# Experience the sample site clone project feature
git clone http://git.lzz.show/lz/lz-git.git
Copy the code

What happens when you run git clone? See git-scm.com/docs/http-p…

  1. Sends a path to the remote end/info/refs? service=git-upload-packGET request to GET reference information for the remote repository
  2. Upon receiving the request, the HTTP service executes the command under the remote repositorygit upload-pack --stateless-rpc --advertise-refs remote/repository/dirAnd returns the command output as an HTTP response to the client
  3. The client initiation path is/git-upload-packTo obtain a remote resource
  4. Upon receiving the request, the HTTP service executes the command under the remote repositorygit upload-pack --stateless-rpc remote/repository/dirAnd returns the command output as an HTTP response to the client
  5. The command is executed

The git push command is similar to the clone command except that the service parameter changes from git-upload-pack to git-receive-pack, and the git command parameter changes from upload-pack to receive-pack

The problem record

Because the content-Type in the HTTP request header initiated by Git is a non-standard header, Express cannot automatically parse the body in the request body, so we need to customize the middleware to parse the body

export function header(req: Request, res: Response, next: NextFunction) {
  if (req.header('Content-Type'.toLowerCase()) === 'application/x-git-upload-pack-request'
    || req.header('Content-Type'.toLowerCase()) === 'application/x-git-receive-pack-request'
    ) {
      const body = [];
      req.on('data'.(chunk) = > {
        body.push(chunk);
      }).on('end'.() = > {
        // Body is converted to buffer format to make it easier to pass the body content as input to git commands
        req.body = Buffer.concat(body);
        next();
      });
    } else{ next(); }};Copy the code

The last

So far, we have preliminarily built a Git code management platform based on Javascript development, and we will continue to look at Github and improve the function. If you think this article is useful to you, welcome to leave a like or welcome to the project site ⭐ open source address

History project

  • Introduction to the Open source microscene editor
  • Start from scratch – Basic flowchart editing library