What are pull requests and forks?

What are pull requests and forks?
MartinKnuth Profile Pic
MartinKnuth,United Kingdom,Professional
Published Date:12-08-2017
Your Website URL(Optional)
Comment
GitHub pull requests GitHub provides more than just Git hosting that you cangit push to andgit fetch from; it also provides features that allow teams of individuals to collaborate on soft- ware projects in ways beyond those provided by Git itself. Two of these features are pull requests and forks. In this chapter you’ll learn about GitHub’s pull requests. 10.1 What are pull requests and forks? One of the core components of most software project collaboration is some sort of issue (or bug) tracker, such as JIRA, FogBugz, Pivotal Tracker, or Trac. GitHub pro- vides an issue tracker for every repository known as Issues. In GitHub’s Issues, there are subject and body fields, an open or closed state, labels, and comments. There is a special type of issue known as a pull request (PR). This is an issue on a project with an attached branch of code changes. Pull requests are used to request 163 164 CHAPTER 10 GitHub pull requests that someone with commit access to the repository merge the code changes from the pull-request branch into their the main repository. Once a PR has been received, you can view the changes that have been requested, and anyone who can view the PR can make comments either inline on the commit or generally on the PR. If there are com- ments that require changes to be made, they can be committed and pushed to the pull-request branch, and the pull request is updated with these changes. Once the PR’s changes have reached an acceptable standard to be included in the repository, you can use the Merge button on the GitHub website to merge the requested branch into the repository. Let’s say you’re creating a new web application and want the master branch to be merged regularly to the web server. You want to ensure that any branches merged into the master branch are always checked by at least one other developer before they’re merged (to be sure nobody accidentally deploys bad code to the server). To do this, you can request that anyone using the project create a pull request rather than merg- ing directly to master and that they receive an OK from at least one other developer before merging to master. If the changes aren’t yet OK, then someone can add more commits to the pull request, and it will be merged when it has been OK’d. Adopting this approach will result in higher-quality code being merged tomaster and fewer silly mistakes, because any new changes will be checked by at least one person other than the original author. Recall from technique 8 that you use git clone to initially download an entire repository. A fork is similar to a clone, but rather than download the repository to your local machine, it creates a clone of a repository on GitHub’s servers. This allows you to make any changes you wish to your fork even if you don’t have commit access to the original repository. Anyone with read access to a repository can fork it. PRs and forks can be combined, so you can find a repository you wish to make changes to, fork it, and make changes in your local fork. You can then create a PR to request the changes on the branch in your fork be merged into the original repository. Let’s return to the web application example. Let’s say you have an open source library that your web application depends on, and you’ve found a bug in it. You want to fix this bug and share it with the open source library maintainers so that they can provide the fix to everyone. But you’ve never worked on this project before, and the maintainers don’t know or trust you yet—thus they’re unlikely to give you commit access to the project so you can fix the bug. Instead, you can fork the repository, make the changes, commit and test them, and then create a pull request from your forked repository to the original repository. This allows the maintainers of the project to review your proposed changes, make any comments, and merge them when they’re ready. This provides a code-review workflow similar to that when using pull requests without forks, but it means anyone can suggest changes without having the ability to merge them. You can read more about using pull requests and forking repositories in GitHub’s official help pages at https://help.github.com/articles/using-pull-requests and TECHNIQUE 59 Making a pull request in the same repository: gh pull-request 165 https://help.github.com/articles/fork-a-repo. I don’t go into more detail here, because these pages are kept up to date with any changes made to GitHub. 10.2 Interacting with GitHub from the command-line: gh You’ve been working mostly from the command line in this book, and PRs are some- times a core part of Git workflows, so it would be useful if you could also create PRs from the command line. Fortunately, a tool called gh lets you interact with GitHub from the command line (through the GitHub API). It’s available for download and provides installation instructions at https://github.com/jingweno/gh. The gh command-line tool allows various interactions with GitHub by providing a wrapper on top of Git’s interface and adding new commands and improving the inter- action of some Git commands with GitHub. For example, instead of running git clone https://github.com/GitInPractice/GitInPracticeRedux, you can run gh clone GitInPractice/GitInPracticeRedux to perform the same action of cloning a GitHub repository to your local machine. The gh tool can also be used to create PRs from the command line. Although this accomplishes the same end result as the web interface and is slightly less flexible, I generally prefer it, because it fits better into the command-line-driven workflow of using the Git to interact with a project’s repository. Technique 59 Making a pull request in the same repository: gh pull-request In my experience, most teams that work on private repositories tend to use a single repository rather than many different forks. Pull requests can still be used on a private repository; even although everyone with read access also has commit access, PRs are still useful for performing code review before changes are merged into a repository. To create a PR, you need to create a local branch of the changes you want to be merged into another branch (master, by default), push the local branch to a remote branch, and usegh to create a pull request. Problem You wish to create a GitHub pull request from the command line. Solution 1 Change to the directory containing your repository: for example, cd /Users/mike/GitInPracticeRedux/. 2 Create a new branch from the master branch by running a command like git checkout -b pr-test master. 3 Make some changes to a file—for example, 00-Preface.asciidoc—and commit them by running git commit 00-Preface.asciidoc. Ensure that there are mul- tiple lines in the commit message: a commit subject and commit body. 166 CHAPTER 10 GitHub pull requests 4 Push the local branch to a remote branch by runninggit push set-upstream origin pr-test. 5 Create a pull request by running gh pull-request, and accept the default pull request message (which should match the commit message). The output for these commands should resemble the following. Listing 10.1 Output: creating a pull request withgh git checkout -b pr-test master Switched to a new branch 'pr-test' Local branch B git commit 00-Preface.asciidoc pr-test 071d468 Preface: use Praxis instead of Paris. 1 file changed, 1 insertion(+), 2 deletions(-) New commit C git push set-upstream origin pr-test Counting objects: 10, done. Delta compression using up to 8 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 348 bytes 0 bytes/s, done. Total 3 (delta 2), reused 0 (delta 0) To https://github.com/GitInPractice/GitInPracticeRedux Remote new branch pr-test - pr-test D branch Branch pr-test set up to track remote branch pr-test from origin. gh pull-request https://github.com/GitInPractice/GitInPracticeRedux/pull/1 Pull request E shows the creation of the new local branch. This is used to commit the changes for B the new pull request. shows the new commit on the pr-test branch. It was created with a commit mes- C sage subject and body. shows the new remote branch that was created to be used for the new pull request. D shows the URL for the new pull request created by the gh tool using the GitHub E API. It requests the merge of the pr-test branch into the remote repository’s master branch. You have created a new pull request from the command line using the gh tool. Discussion HOW DO YOU USE BRANCHES WITH PULL REQUESTS? Each pull request you cre- ate should use a new, non-master branch. Because each pull request tracks the status (and any new commits) for a particular remote branch, you need to ensure that each branch is used for a separate pull request to avoid situations like adding a new commit to one pull request and having it show up in another. You should also avoid creating pull requests from themaster branch, because this is generally the branch you will want to merge to. Additionally, TECHNIQUE 59 Making a pull request in the same repository: gh pull-request 167 GitHub sometimes doesn’t update the master branch if you push new com- mits to it after creating the pull request, so you’d need to create a new pull request for every change that needs to be made. This is less than ideal, because you lose all the existing context and comments. Now that a pull request has been created, you can view it in the GitHub web interface. Figure 10.1 shows the new pull request created on GitHub. gh defaulted the pull- request message to that of the single commit in this pull request. You can see that the commit message subject was used for the title of the pull request and the commit mes- sage body was used as the initial comment. Additionally, the master branch was used as the base branch, which is the branch into which the PR requests the changes be merged. The changes that should be merged in are those from the pr-test branch, which is known as the head branch. Essentially, the pull request has created a remote branch named pr-test. You’ve requested that someone merge it into themaster branch and discuss any changes that need to be made. The gh tool also accepts the -b and -h parameters, which can be followed with a branch name to change the base and head branches, respectively. These can be passed either a branch name such as pr-test; a branch name and GitHub user/orga- nization name such as GitInPractice:pr-test; or a GitHub user/organization name, repository name, and branch name, as in GitInPractice/GitInPractice- Redux:pr-test. Figure 10.1 New pull request 168 CHAPTER 10 GitHub pull requests HOW CAN YOU VIEW A PULL REQUEST WITHOUT WHITESPACE CHANGES? The Files Changed pane on a pull request shows a diff of the changes in that pull request. Some lines may have changes to whitespace that you don’t care about. In this case, you can avoid them by appending ?w=1 to the Files Changed URL: for example, https://github.com/GitInPractice/ GitInPracticeRedux/pull/1/files?w=1. Technique 60 Making a pull request from a forked repository: gh fork If you want to commit to an open source software project that you don’t have commit access to, you’ll want to create a pull request so others can review your changes before they’re merged (because open source doesn’t mean letting anyone commit to any repository at any time). To do this, you create your own repository to which you can make commits and push branches, and from which you can request pull requests. As you may recall from section 10.1, you can fork any repository you have read access to (which includes all public, open source repositories). Problem You wish to fork a repository and create a pull request from that fork from the com- mand line. Solution 1 Change to the directory containing your repository: for example, cd /Users/mike/GitInPracticeRedux/. 2 Create a new fork by running gh fork. 3 Create a new branch from the master branch by running a command like git checkout -b credits master. 4 Make some changes to a file—for example, 01-IntroducingGitInPractice.ascii- doc—and commit them by running git commit 01-IntroducingGitIn- Practice.asciidoc. Ensure that there are multiple lines in the commit message: a commit subject and commit body. 5 Push the local branch to a remote branch by running, for example, git push set-upstream origin pr-test. 6 Create a pull request by running gh pull-request, and accept the default pull- request message (which should match the commit message). The output for these commands should resemble the following. Listing 10.2 Output: creating a fork and a pull request withgh gh fork remote: Counting objects: 3, done. remote: Compressing objects: 100% (3/3), done. remote: Total 3 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (3/3), done. TECHNIQUE 61 Merging a pull request from the same repository 169 From https://github.com/mikemcquaid/GitInPracticeRedux new branch inspiration - mikemcquaid/inspiration new branch master - mikemcquaid/master new branch pr-test - mikemcquaid/pr-test new branch v0.1-release - mikemcquaid/v0.1-release new remote: mikemcquaid Repository fork B git checkout -b credits Switched to a new branch 'credits' Local branch C git commit 01-IntroducingGitInPractice.asciidoc credits e9d27c7 Chapter 1: attribute quote. 1 file changed, 2 insertions(+), 2 deletions(-) New commit D git push set-upstream origin credits Counting objects: 10, done. Delta compression using up to 8 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 348 bytes 0 bytes/s, done. Total 3 (delta 2), reused 0 (delta 0) To https://github.com/mikemcquaid/GitInPracticeRedux Remote new branch credits - credits E branch Branch credits set up to track remote branch credits from origin. gh pull-request https://github.com/GitInPractice/GitInPracticeRedux/pull/2 Pull request F shows that the repository was forked on GitHub, and a new remote repository was B added with the username of the fork (mikemcquaid in this case) and then fetched. shows the creation of the new local branch. C shows the new commit on the credits branch. D shows the new remote branch that was created. E shows the URL for the new pull request. It’s requesting the merge of the credits F branch from the https://github.com/mikemcquaid/GitInPracticeRedux forked repository into themaster branch of the https://github.com/GitInPractice/GitIn- PracticeRedux main repository. You have created a fork and a pull request from it from the command line. Technique 61 Merging a pull request from the same repository Merging a pull request from a non-forked repository is easy. You can either click the Merge Pull Request button (as shown in figure 10.1) or merge the branch as you would any other. Note that the Merge Pull Request button always performs a non-fast- forward merge (it always produces a merge commit), so let’s do that here too. Problem You wish to merge a pull request from the command line. 170 CHAPTER 10 GitHub pull requests Solution 1 Change to the directory containing your repository: for example, cd /Users/mike/GitInPracticeRedux/. 2 Check out the master branch by running git checkout master. 3 Ensure that all the remote branches are up to date by running git fetch. 4 Merge the remote pr-test branch into the master branch by running git merge no-ff origin/pr-test. 5 Push the updated master branch with git push. 6 Delete the now-mergedpr-test branch by runninggit push delete origin pr-test. The output for these commands should resemble the following. Listing 10.3 Output: merging a pull request git checkout master Switched to branch 'master' Your branch is up-to-date with 'origin/master'. Branch checkout B git fetch git merge no-ff origin/pr-test Merge made by the 'recursive' strategy. 00-Preface.asciidoc 3 + 1 file changed, 1 insertion(+), 2 deletions(-) Merge commit C git push Counting objects: 1, done. Writing objects: 100% (1/1), 241 bytes 0 bytes/s, done. Total 1 (delta 0), reused 0 (delta 0) To https://github.com/GitInPractice/GitInPracticeRedux.git cc206b5..7a19d89 master - master Branch push D git push delete origin pr-test To https://github.com/GitInPractice/GitInPracticeRedux.git - deleted pr-test Branch delete E shows the checkout of the master branch. This is required, because to merge into B the master branch, you first need to have themaster branch checked out. shows the new merge commit created by the non-fast-forward commit. Remember, C this was run with no-ff to guarantee creating a merge commit (which matches the behavior of the Merge Pull Request button). shows the new merged commits being pushed to the remote master branch. D shows the deletion of the now merged (and therefore unneeded) pr-test branch. E You have successfully merged a pull request from the command line. TECHNIQUE 61 Merging a pull request from the same repository 171 Discussion Let’s look at the pull request on GitHub. Figure 10.2 shows the state of the merged pull request after these changes. You’ll notice that after the push, the pull request is automatically closed, because it has detected that you’ve merged the contents of the branch remotely. HOW CAN YOU CLOSE A PULL REQUEST WITHOUT A MERGE OR ISSUE FROM A COMMIT? If you prefer to cherry-pick or rewrite some of the commits, the SHA-1 may change. This may not be detected automatically by GitHub as a merge, and therefore the issue may not be closed automatically. If you wish to ensure that any modified commit automatically closes the pull request, you can use git rebase interactive or git commit amend to change the commit message for one of the commits to include text such as Closes 1. The first pull request that was created in the example was numbered 1. This magic string in a commit message is detected by GitHub and indicates that when this commit is merged to the master branch on the main repository, it should close the pull request or issue numbered 1. You can read more about this in GitHub’s help at https://help.github.com/articles/closing-issues-via- commit-messages. Figure 10.2 Merged pull request 172 CHAPTER 10 GitHub pull requests Technique 62 Merging a pull request from a forked repository: gh merge Merging a pull request from a forked repository is more involved. You can click the Merge Pull Request button, but what if you want to merge the branch from the com- mand line? You could manually add the forked repository as a remote repository and merge it like before. Instead, though, let’s use the handy gh tool again to make things a bit easier. To simulate the typical open source maintainer approach where new forks aren’t already added as remote repositories, let’s start by removing the fork’s remote from the local Git repository by runninggit remote rm mikemcquaid (which won’t produce any output). This leaves the remote intact on GitHub, but it’s no longer on the local repository. Problem You wish to merge a pull request from a forked repository from the command line. Solution 1 Change to the directory containing your repository: for example, cd /Users/mike/GitInPracticeRedux/. 2 Check out the master branch by running git checkout master. 3 Merge the remote pull request into the master branch by running gh merge https://github.com/GitInPractice/GitInPracticeRedux/pull/2. 4 Push the updated master branch with git push. The output for these commands should resemble the following. Listing 10.4 Output: merging a pull request from a forked repository git checkout master Switched to branch 'master' Your branch is up-to-date with 'origin/master'. Branch checkout B gh merge https://github.com/GitInPractice/GitInPracticeRedux/pull/2 From https://github.com/mikemcquaid/GitInPracticeRedux new branch credits - mikemcquaid/credits Merge made by the 'recursive' strategy. 01-IntroducingGitInPractice.asciidoc 4 ++ 1 file changed, 2 insertions(+), 2 deletions(-) PR merge C git push Counting objects: 12, done. Delta compression using up to 8 threads. Compressing objects: 100% (5/5), done. Writing objects: 100% (5/5), 620 bytes 0 bytes/s, done. Total 5 (delta 3), reused 0 (delta 0) To https://github.com/GitInPractice/GitInPracticeRedux.git Summary 173 7a19d89..77f848d master - master Branch push D shows the checkout of the master branch. B shows the new merge commit created by the pull-request merge. C shows the new PR commits being pushed to the remote master branch. D You have successfully merged a pull request from a forked repository from the com- mand line. 10.3 Summary In this chapter you learned the following:  How pull requests are used to request the merge and review of branches  How forks are used to request pull requests on repositories without commit access  How to create a new pull request using gh pull-request  How to merge a pull request using git merge or gh merge Hosting a repository This chapter covers  Creating a repository in a format for hosting a server  Mirroring an existing repository for hosting a server  Sharing a repository with a local network  Viewing a repository in a web browser  Providing advanced Git hosting with other software You saw in technique 6 how to push to remote repositories, provided by various organizations on the internet, as a way of sharing your Git repositories with others. Sometimes, though, you may wish to host a remote Git repository on a machine you control—for example, to  Temporarily share a Git repository on your machine with another computer on the same network  Keep a full backup of an external Git repository on a server you control  Provide an internal mirror of an external Git repository to allow faster trans- fer speeds  Host a Git repository on a server entirely under your own control I only use the commands in this chapter to view a local repository or share a local repository with computers on the same network (rather than over the internet). Although you’ll see more advanced tools in section 11.1, this chapter focuses on 174 TECHNIQUE 63 Initializing a local repository in a server hosting format: git init bare 175 understanding the features provided by Git itself and how they work, rather than more advanced Git hosting solutions. In essence, this chapter is a guide for software engineers to understand how Git repositories can be shared and not a guide for sys- tem administrators on how to set up Git servers. Unless you’re an experienced system administrator, I’d advise using an external Git hosting provider (such as GitHub) rather than running your own Git servers. Technique 63 Initializing a local repository in a server hosting format: git init - -bare The Git repositories you’ve seen throughout this book have all had a similar structure: the working directory contains a checkout of the files in the current branch and a .git subdirectory that contains the repository data. For example, if you had a GitIn- PracticeNonBare.git repo, its contents might resemble figure 11.1. You can see that it has only the README.md file and the .git repository data subdi- rectory in the root. Git stores data in a highly space-efficient format. The checked-out files in a repository’s working directory may sometimes take up more space than the compressed version of all files stored in the .git directory On a server, the working directory should never be used directly, so it’s better to not create one at all. Because you’ll be sending/receiving Git objects to/from various Git clients with git push, git fetch, and git pull, you don’t need to have the actual files checked out on disk. A Git repository without a working directory is known as a bare repository. The major difference compared to the first repository you created in technique 1 is that this repository isn’t in a .git directory. Figure 11.1 Typical Let’s create a bare repository and look at its contents. repository layout Problem You wish to create a bare Git repository. Solution 1 Change to the directory you wish to contain your new repository directory: for example, cd /Users/mike/. 2 Run git init bare GitInPracticeBare.git. The output should resemble the following. Listing 11.1 Output: initializing a bare repository git init bare GitInPracticeBare.git Initialized empty Git repository in /Users/mike/GitInPracticeBare.git/ B shows the new directory that was created for the bare Git repository. B 176 CHAPTER 11 Hosting a repository You have successfully created a new bare Git repository. Discussion Bare repositories don’t allow new commits to be created locally; they must be pushed from another repository. HOW SHOULD YOU NAME BARE REPOSITORIES? When creating bare reposito- ries, it’s good practice to name them with the extension .git to make it clear that they’re bare. Let’s look at the layout of a bare repository; see figure 11.2. You can see that the repository data that was stored in .git in figure 11.1 is instead in the root in figure 11.2. This means the root of the repository is effectively the .git directory (which is why it’s named GitInPracticeBare.git). The bare repository is miss- ing an index file and a logs directory and instead has a packed- refs file. These differences are internal Git files that are used for repositories; don’t worry about their contents (although Figure 11.2 Bare you’ll see the packed-refs file in technique 64). repository layout To clone this Git repository into a non-bare repository on the same machine, run git clone with the path on disk to the repository and the new, non-bare repository name as arguments: for example, git clone /Users/mike/ GitInPracticeBare.git GitInPracticeNonBare. In this case, the output will resem- ble the following: Cloning into 'GitInPracticeNonBare.git'... warning: You appear to have cloned an empty repository. done The new repository has been created, but it’s empty—it contains no commits. If you add a file, commit, and push it, it will be pushed to the bare repository and both repositories will be non-empty. Note that you’d never usually clone a bare repository on the same machine but would instead create a bare repository on one machine and clone it on another. Personally, I’ve only used bare repositories to create mirrors of existing reposito- ries on a server I control. I didn’t care about having the files checked-out into the working directory; I just wanted a copy of all the repository data. Let’s learn how to use Git to create an exact mirror of another repository. Technique 64 Mirroring a repository: git clone - -mirror There are times when you wish to host a new Git repository that’s a mirror of another—a functionally identical copy. This could be for backup, providing a local cache for increased speed, or moving a repository to another location. Recall from technique 8 that git clone creates a clone of the repository locally with all commits, branches, and tags that are in the repository you’ve cloned from. TECHNIQUE 64 Mirroring a repository: git clone mirror 177 If you git clone a repository with a branch namedtesting, your new, local clone will contain a remote branch named origin/testing. But what if you wanted this to create not only the origin/testing remote branch but also a local branch named testing? In this case, you’d use the mirror flag for git clone, which creates local branches for all remote branches it finds (or, in Git terminology, matches all refs locally). This is useful when you want to create an exact copy of another repository (a mirror) so others can clone from it and get the same results as cloning from the origi- nal repository, or to keep as a backup. Recall the discussion of forks on GitHub from section 10.1. git clone mirror is effectively what GitHub does when you fork a repository: it makes a complete copy that can be modified without changing the origi- nal repository and creates all the same branches. Let’s use git clone mirror to set up a local mirror of the GitInPracticeRedux repository. Problem You wish to mirror an existing remote repository. Solution 1 Change to the directory you wish to contain your new repository directory: for example, cd /Users/mike/. 2 Run git clone mirror https://github.com/GitInPractice/GitInPractice Redux.git. The output should resemble the following. Listing 11.2 Output: cloning a mirror git clone mirror https://github.com/GitInPractice/GitInPracticeRedux.git Cloning into bare repository 'GitInPracticeRedux.git'... Bare repository B remote: Reusing existing pack: 79, done. remote: Counting objects: 1, done. remote: Total 80 (delta 0), reused 1 (delta 0) Unpacking objects: 100% (80/80), done. Checking connectivity... done. shows that git clone mirror creates a bare repository when it creates a mirror. B This is because mirror is used only when hosting a repository for other reposito- ries to pull from. You have mirrored the existing GitInPracticeRedux repository. Discussion As explained in technique 8, git clone can take the following tags:  No flags—Creates a normal (non-bare) repository with remote branches  bare flag—Creates a bare repository with remote branches 178 CHAPTER 11 Hosting a repository  mirror flag—Creates a bare repository with remote branches and local branches for every remote branch Let’s examine the contents of the GitInPracticeRedux.git/packed-refs file: pack-refs with: peeled fully-peeled ca74d2b7c4dd15a260e68c6ff3552c64041aacdc refs/heads/inspiration a9e150fb17301eed6c31aa984411effdab8f3fec refs/heads/master Branch a8200e1407d49e37baad47da04c0981f43d7c7ff refs/heads/v0.1-release 071d468df295c3866054763250a1344e44f8c3be refs/pull/1/head 75f9dd1ddc24e1fd9e58b8443f7f0176cf7bd2e7 refs/pull/1/merge Pull e9d27c7df49c07cb2325356ab9a76f90d9f179ae refs/pull/2/head request e6e9208372f3784686499430fec547c20dad6139 refs/pull/2/merge 725c33ace6cd7b281c2d3b342ca05562d3dc7335 refs/tags/v0.1 Tag The packed-refs file contains all the packed refs (refs in Git’s format for data internal and external transfer) that were fetched from the GitInPracticeRedux repository. It contains all the created branches, pull requests, and tags that were created in this repository. These will now be shared with any other repositories that clone this one. Technique 65 Sharing a repository with other users on the same network: git daemon Now that you’ve seen how to create bare repositories suitable for a server to share with other Git repositories, let’s learn how to serve these to other Git clients. In technique 63, you saw a repository being cloned from another path on the disk. Although this would be one way of sharing a repository over the network with Git (giving someone access to your disk with, say, a network share), it’s not very efficient, because it uses multiple pro- tocols: the SMB protocol to share the files over the network, and Git’s interaction with the packed repository. Instead, a Git server allows Git to interact natively in its own for- mat and git:// protocol, which transfers repository data in a format similar to how it’s stored locally and defaults to using port 9418. Git provides a simple command for basic repository hosting named git daemon. It provides no user authentication or encryption and only supports the git:// protocol (rather than the https:// you’ve used throughout this book, or ssh://, which uses SSH access). These protocols are fairly interchangeable; which one you pick will depend mostly on whether you need to use HTTP proxies or web servers (for the https:// pro- tocol), user authentication using SSH (for the ssh:// protocol), or no authentication (for the git:// protocol). This command may be too limited for some cases, but it’s great for this technique. Problem You wish to share a repository with other users on the same network. Solution 1 Change directory to the Git repository: for example, cd /Users/mike/GitInPracticeRedux.git/. TECHNIQUE 65 Sharing a repository with other users on the same network: git daemon 179 2 Run git daemon verbose base-path=. export-all. The output should resemble the following. Listing 11.3 Output: daemon git daemon verbose base-path=. export-all Daemon arguments B 72938 Ready to rumble Process ready C shows the daemon command and the list of arguments required to export the Git B repository. These are elaborated on in the discussion section. shows the process ID (72938), that the process has started successfully, and that it’s C ready to receive clients. Now that you have git daemon running, open another terminal window and clone this repository from a client with git clone git://localhost/: git clone git://localhost/ GitInPracticeReduxDaemon Local server B Cloning into 'GitInPracticeReduxDaemon'... remote: Counting objects: 78, done. remote: Compressing objects: 100% (71/71), done. remote: Total 78 (delta 26), reused 0 (delta 0) Receiving objects: 100% (78/78), 7.80 KiB 0 bytes/s, done. Resolving deltas: 100% (26/26), done. Checking connectivity... done. shows that you’re using localhost to access the Git daemon on the same machine B you’re hosting it on. It has cloned the repository as expected into a new directory on the same machine. If you wanted to clone this from another machine, you’d replace localhost in the command with the IP address of the machine hosting the daemon on the network: for example, git clone git://192.168.0.123/. If you view the daemon output again, you’ll see that some lines have been added: 72984 Connection from ::1:52891 Client connection 72984 Extended attributes (16 bytes) exist host=localhost Attribute exposure 72984 Request upload-pack for '/' Repository upload 72938 72984 Disconnected Client disconnect These lines show that the Git client connected to the server, the repository exposed some attributes to the client, the client requested that the server upload its contents to the client, and the client then disconnected from the server. You have successfully shared a repository over the network. Discussion git daemon can take some parameters to customize its behavior: 180 CHAPTER 11 Hosting a repository  verbose—Outputs more verbose log details to the terminal about incoming Git client connections and access successes and failures. It’s useful when host- ing a server to enable this for debugging.  base-path=.—Indicates what path should be used as the server root. In this case, you only hosted a single repository, so you set the root to the base direc- tory of the repository. If you wanted to host a directory that contained multiple repositories (such as fish.git and cat.git), you could specify the directories, and then they could be accessed by name (git clone git://localhost/ fish.git or git clone git://localhost/cat.git). I tend to only use git daemon to share a single repository, so I use base-path=..  export-all—Tells Git to allow access to all Git repositories under the base path. Without this argument, by default git daemon only allows access to reposi- tories that have a git-daemon-export-ok file in the repository root (the root for bare repositories and .git for non-bare repositories). I tend to use this, because I use git daemon so infrequently and only on repositories I explicitly, currently want to share.  enable=receive-pack—Allows write access to the repository. By default, git daemon only allows read access (provided by upload-pack) to repositories unless this flag is provided. It’s not recommended that you provide write access to non-bare repositories, because it would be undesirable for remote users to be able to change the contents of your local branches.  directory—Needed if you wish to host a non-bare repository. In this case, you’d cd into the directory as normal but add a ./.git argument specifying that you want to share the .git directory. For example, you might run cd /Users/mike/ GitInPracticeRedux && git daemon verbose base-path=. export-all ./.git. I use this when temporarily hosting non-bare repositories that I’m working with on my local machine with others. Technique 66 Displaying a repository in a browser: git instaweb Now that you’ve shared your repository on disk with other users, it would be useful if you could provide a basic web interface to go along with your git daemon. Git pro- vides a basic web interface named gitweb that can be hosted by a local web server. HOW CAN YOU INSTALL GITWEB? Gitweb is usually installed as part of the default Git installation (and is in all the official Git installers). If it hasn’t been, you’ll need to install it separately. This can be done by installing gitweb (or similar) with your package manager: for example, on Debian/Ubuntu, run apt-get install gitweb. Git provides the git instaweb command to host your local repository using the git- web interface. To run this, you must have a web server installed on your machine. If you’re using OS X, you can use WEBrick, which is a simple web server provided with Ruby (which is provided with OS X). If you’re on Linux, you can install Ruby with your TECHNIQUE 66 Displaying a repository in a browser: git instaweb 181 package manager: for example, on Debian/Ubuntu, run apt-get install ruby (you’ll use WEBrick on Linux to be consistent with OS X). Windows Git installation sadly doesn’t provide thegit instaweb command, but you can read how to set up git- web using a separate web server such as Apache or IIS here: https://git.wiki .kernel.org/index.php/MSysGit:GitWeb. Now that you have git instaweb set up, let’s use it to display the repository in a browser. Problem You wish to display the contents of a repository in a browser. Solution 1 Change to the directory containing your repository: for example, cd /Users/mike/GitInPracticeRedux/. 2 Write a description for the repository’s web server by running echo "Git In Practice: Redux" .git/description. 3 Run git instaweb httpd=webrick. There will be no output. Git opens the gitweb interface in your browser; it should resemble figure 11.3. You can see that it displays a single Git project along with the description you just set, the owner, and the last change (commit) date. Click the Summary button to view more information about the GitInPracticeRedux project. Figure 11.3 Gitweb projects The summary page in figure 11.4 displays the same information as the projects page but also shows the list of recent commits, branches, and tags in a format resembling GitX/gitk. Detailing all the features of the gitweb interface is beyond the scope of this book, but it’s pretty self-explanatory. After you’ve finished exploring the gitweb interface, you can stop the server by running git instaweb stop. You have successfully displayed the contents of the repository in a browser. 182 CHAPTER 11 Hosting a repository Figure 11.4 Gitweb summary Discussion git instaweb can take some parameters to customize its behavior:  local—Ensures that the web server can only be accessed from the local machine and not from other machines on the same network.  port—Can be followed by a port number to specify which port should be used to access gitweb. For example,port 8080 means gitweb is hosted on port 8080. 11.1 Advanced Git hosting In addition to the tools provided with Git that you’ve seen in this chapter, there is a wide third-party ecosystem of Git tools that can help you share your repositories and provide a web interface to view them. There are too many and their setup is too involved for me to detail them all here. Some of the most popular options are as follows:  GitHub (https://github.com) is the most widely used Git host. It offers many features beyond sharing and viewing Git repositories. It provides free open source public hosting and paid private hosting. Alternatively, you can pay for GitHub Enterprise (https://enterprise.github.com), which provides a hosted GitHub appliance that can be run inside your network.  cgit (https://github.com/zx2c4/cgit) provides a fast Git web interface written in C. It uses forking and a cache to speed up operations and is widely used by open source projects.  gitolite (https://github.com/sitaramc/gitolite) provides access control for host- ing Git repositories, such as users, groups, per-branch/per-repository permis- sions, and hook support.

Advise: Why You Wasting Money in Costly SEO Tools, Use World's Best Free SEO Tool Ubersuggest.