Difference between revisions of "Git"

From ArchWiki
Jump to: navigation, search
m (Corrected git clone git@github.com:torvalds/linux.git to git clone git://github.com/torvalds/linux.git)
(Installation: link to aspell)
 
(239 intermediate revisions by 36 users not shown)
Line 1: Line 1:
 
[[Category:Version Control System]]
 
[[Category:Version Control System]]
 +
[[ja:Git]]
 
[[zh-CN:Git]]
 
[[zh-CN:Git]]
{{Article summary start}}
+
{{Related articles start}}
{{Article summary text|Installing and using the Git VCS}}
+
{{Related|Gitweb}}
{{Article summary heading|Related}}
+
{{Related|Cgit}}
{{Article summary wiki|Super Quick Git Guide}}: Generally about contributing to pacman, although it still serves as a practical Git tutorial
+
{{Related|HTTP tunneling#Tunneling Git}}
{{Article summary wiki|Gitweb}}
+
{{Related|Subversion}}
{{Article summary wiki|Cgit}}
+
{{Related|Concurrent Versions System}}
{{Article summary wiki|Subversion}}
+
{{Related articles end}}
{{Article summary wiki|Concurrent Versions System}}
+
{{Quote|I've met people who thought that git is a front-end to GitHub. They were wrong, git is a front-end to AUR.|Linus Torvalds}}
{{Article summary link|GitHub|https://github.com/}}
+
{{Article summary end}}
+
  
[http://git-scm.com/ Git] is the version control system (VCS) coded by Linus Torvalds (the creator of the Linux kernel) after being criticized for using the proprietary BitKeeper with the Linux kernel. Git is now used to maintain sources for the Linux kernel as well as thousands of other projects, including [[Pacman]], Arch's package manager.
+
[[wikipedia:Git (software)|Git]] is the version control system (VCS) designed and developed by Linus Torvalds, the creator of the Linux kernel. Git is now used to maintain [[AUR]] packages, as well as many other projects, including sources for the Linux kernel.  
  
There is extensive documentation, including guides and tutorials, available from the [http://git-scm.com/documentation official web site].
+
== Installation ==
  
==Installation==
+
[[Install]] the {{Pkg|git}} package. For the development version, install {{AUR|git-git}} from the AUR. Check the optional dependencies when using tools such as ''git svn'', ''git gui'' and ''gitk''.
{{Pkg|git}} can be installed with [[pacman]] from the [[Official Repositories|official repositories]]. If you care about using Git with other VCS software, mail servers, or using Git's GUI, pay close attention to the optional dependencies.
+
  
Bash completion (e.g. hitting {{ic|Tab}} to complete commands you are typing) should work if you add this line to your {{ic|~/.bashrc}} file:
+
{{Note|To enable spell checking in ''git-gui'', {{Pkg|aspell}} is required, along with the dictionary corresponding to the {{ic|LC_MESSAGES}} [[environment variable]]. See {{Bug|28181}} and the [[aspell]] article.}}
{{bc|source /usr/share/git/completion/git-completion.bash}}
+
Alternatively, you can install the {{Pkg|bash-completion}} package to load the completions automatically for new shells.
+
 
+
If you want to use Git's built-in GUI (e.g. {{Ic|gitk}} or {{Ic|git gui}}) you should install the {{Pkg|tk}} package, or you will get a rather cryptic message:
+
{{bc|/usr/bin/gitk: line 3: exec: wish: not found.}}
+
  
 
== Configuration ==
 
== Configuration ==
Git reads its configuration from a few INI type configuration files.  In each git repository {{ic|.git/config}} is used for configuration options specific to that repository.  Per-user ("global") configuration in {{ic|$HOME/.gitconfig}} is used as a fall-back from the repository configuration.  You can edit the files directly but the preferred method is to use the git-config utility. For example,
 
$ git config --global core.editor "nano -w"
 
adds {{Ic|<nowiki>editor = nano -w</nowiki>}} to the {{Ic|<nowiki>[core]</nowiki>}} section of your {{ic|~/.gitconfig}} file.
 
  
The [http://schacon.github.com/git/git-config.html man page for the git-config] utility has a fairly long list of variables which can be set.
+
In order to use Git you need to set at least a name and email:
  
The two settings you should set before using Git are your name and email. These are used to sign commits you make.
+
  $ git config --global user.name "''John Doe''"
  $ git config --global user.name "Firstname Lastname"
+
  $ git config --global user.email "''johndoe@foobar.com''"
  $ git config --global user.email "your_email@youremail.com"
+
  
===Colors in Git Prompt===
+
See [[#Tips and tricks]] for more settings.
{{ic|color.ui}} is also a very useful option to set - it colorizes all Git output.
+
$ git config --global color.ui true
+
  
==Basic Usage==
+
== Usage ==
  
===Cloning a repository===
+
This tutorial teaches how to use Git for basic distributed revision control of a project.
  
git clone <repo location> <dir>
+
Git is a distributed version control system, which means that the entire history of changes to a repository is stored locally, in a directory called {{ic|./.git}} in the project directory. The project files which are visible to the user constitute the ''working tree''. These files can be updated to match revisions stored in {{ic|./.git}} using {{ic|git}} commands (e.g. {{ic|git checkout}}), and new revisions can be created in turn by editing these files and running the appropriate {{ic|git}} commands (e.g. {{ic|git commit}}).
  
will clone a Git repository in a new directory inside your current directory. Leaving out {{ic|<dir>}}
+
See {{ic|man gitglossary}} for more complete definitions of the terms used in this tutorial.
will cause it to name the folder after the Git repository. For example,
+
  
git clone git://github.com/torvalds/linux.git
+
A typical Git work-flow is:
  
clones Github's mirror of the Linux kernel into a directory named "linux".
+
# Create a new project or clone a remote one.
 +
# Create a branch to make changes; then commit those changes.
 +
# Consolidate commits for better organization/understanding.
 +
# Merge commits back into the main branch.
 +
# (Optional) Push changes to a remote server.
  
===Committing files===
+
=== Local repository ===
  
Git's commit process involves two steps:
+
==== Staging operations ====
  
# Add new files, add changes for existing files (both with {{ic|git add <files>}}), and/or remove files (with {{ic|git rm}}). These changes are put in a staging area called the index.
+
'''Initialize''' a new repository. This creates and initializes {{ic|./.git}}:
# Call {{ic|git commit}} to commit the changes.
+
  
Git commit will open up a text editor to provide a commit message.
+
$ cd (your project)/
You can set this editor to whatever you want by changing the {{ic|core.editor}} option with {{ic|git config}}.
+
$ git init
  
Alternatively, you can use {{ic|git commit -m <message>}} to supply the commit message without opening the text editor.
+
To record the changes to the repository, they must first be added to the ''index'', or ''staging area'', with an operation often also referred to as ''staging''. When you commit changes using {{ic|git commit}}, it is the contents of the index which are committed to the current branch, not the contents of the working tree.
  
Other useful commit tricks:
+
{{Note|The index is actually a binary file {{ic|.git/index}}, which can be queried with {{ic|git ls-files --stage}}.}}
  
{{ic|git commit -a}} lets you commit changes you have made to files already under Git control
+
To '''add files''' to the index from the working tree:
without having to take the step of adding the changes to the index. You still have to add new files with git add.
+
  
{{ic|git add -p}} lets you commit specific parts of files you have changed.
+
$ git add ''file1'' ''file2''
This is useful if you have made a bunch of changes that you think would be best split into several commits.
+
  
===Pushing your changes===
+
This records the current state of the files. If the files are subsequently modified, you can run {{ic|git add}} again to "add" the new versions to the index.
  
To push your changes up to a server (such as Github), use
+
'''Add all''' files:
  
  git push <server name> <branch>
+
  $ git add .
  
Adding {{ic|-u}} will make this server the default one to push to for this branch.
+
{{Tip|To '''ignore''' some files from, e.g. {{ic|git add .}}, create a {{ic|.gitignore}} file (or files):
If you have cloned the repository as described above, the server will default to the location you cloned the
+
repository from (nicknamed "origin") and the branch will default to the master branch.
+
In other words, if you have followed this guide's instructions in cloning, {{ic|git push}} will suffice.
+
You can set up Git to push to multiple servers if you want, but that is a more advanced topic.
+
Branches will be discussed later in this guide.
+
  
===Pulling from the server===
+
{{hc|.gitignore|
 +
# File I'll likely delete
 +
test-script
  
If you are working on multiple machines and want to update your local repository to what the server has, change directory into your local repository and use
+
# Ignore all .html files, except 'important.html'
 +
*.html
 +
!important.html
  
git pull <server name> <branch>
+
# Ignore all files recursively in 'DoNotInclude'
 +
DoNotInclude/**
 +
}}
  
Similarly to push, the server name and branch should have sane defaults, so {{ic|git pull}} should suffice.
+
See [http://git-scm.com/docs/gitignore gitignore(5)] for details.
Git pull is actually shorthand for doing two things:
+
}}
  
# Calling {{ic|git fetch}}, which updates the local copy of what the server has. Such branches are called "remote" branches because they are mirroring remote servers.
+
'''Remove''' a file from staging ({{ic|--cached}} preserves the actual file(s)):
# Calling {{ic|git merge}}, which merges what the remote branch has with what you have. If your commit history is the same as the server's commit history, you will be automatically fast-forwarded to the latest commit on the server. If your history does not match (maybe someone else has pushed commits since you last synced), the two histories will be merged.
+
  
It is not a bad idea to get into the practice of using these two commands instead of {{ic|git pull}}. This way you can
+
$ git rm ''(--cached)'' ''file''
check to make sure that the server contains what you would expect before merging.
+
  
===Examining history===
+
'''Remove all''' files:
  
The command {{ic|git log}} shows the history of your current branch. Note that each commit is identified by a SHA-1 hash.
+
$ git rm --cached -r .
The author, commit date, and commit message follow. A more useful command is
+
  
git log --graph --oneline --decorate
+
Or:
  
which provides a display similar to TortoiseGit's log window. It shows the following:
+
$ git reset HEAD -- .
  
* The first 7 digits of each commit's SHA-1 hash (enough to be unique)
+
Here, {{ic|HEAD}} is a "symbolic reference" to the current revision.
* The {{ic|--graph}} option shows how any branches (if there are others) fork off from the current branch.
+
* The {{ic|--oneline}} option shows only the first line of each commit message
+
* The {{ic|--decorate}} option shows all commit labels (branches and tags)
+
  
It may be convenient to alias this command as {{ic|git graph}} by doing the following:
+
'''Rename''' a file:
  
  git config --global alias.graph 'log --graph --oneline --decorate'
+
  $ git mv ''file1'' ''file2''
  
Now typing {{ic|git graph}} will run {{ic|git log --graph --oneline --decorate}}.
+
{{Note|{{ic|git mv}} is a convenience command, roughly equivalent to {{ic|mv file1 file2}} followed by {{ic|git rm file1}} and {{ic|git add file2}}. Rename detection during merges is based only on content similarity, and ignores the actual commands used to rename files. The broader rationale for this approach, which distinguishes Git from patch-based systems like [[Darcs]], can be found [http://permalink.gmane.org/gmane.comp.version-control.git/217 here].}}
{{ic|git graph}} and {{ic|git log}} may be given the {{ic|--all}} flag in order to view all branches instead of just the current one.
+
Adding {{ic|--stat}} to one of these commands is also useful -
+
it shows which files each commit changed and how many lines were changed in each file.
+
  
===Dealing With Merges===
+
'''List''' files:
  
Merges happen when you pull, as a result of a rebase operation, and when you merge one branch into another.
+
$ git ls-files
Like other version control tools, when Git cannot automatically merge a commit, it turns to you.
+
See [http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging#Basic-Merge-Conflicts this section]
+
of the Git Book for an explanation on how to resolve merge conflicts.
+
If you screw up and would like to back out of the merge, you can usually abort the merge using the {{ic|--abort}} flag
+
with whatever command started the merge (e.g. {{ic|git merge --abort}}, {{ic|git pull --abort}}, {{ic|git rebase --abort}}).
+
  
==Taking Advantage of DVCS==
+
By default this shows files in the staging area ({{ic|--cached}} files).
  
The above commands only provide the basics.
+
==== Commit changes ====
The real power and convenience in Git (and other distributed version control systems) come from leveraging its local commits and fast branching.
+
A typical Git workflow looks like this:
+
  
# Create and check out a branch to add a feature.
+
Once the content to be recorded is ''staged'', '''commit''' them with:
# Make as many commits as you would like on that branch while developing that feature.
+
# Squash, rearrange, and edit your commits until you are satisfied with the commits enough to push them to the central server and make them public.
+
# Merge your branch back into the main branch.
+
# Delete your branch, if you desire.
+
# Push your changes to the central server.
+
  
===Creating a branch===
+
$ git commit -m "''First commit.''"
  
git branch <branch name>
+
The {{ic|-m (''--message)}}'' option is for a short message: if omitted, the preset editor will be spawned to allow entering a longer message.
  
can be used to create a branch that will branch off the current commit.
+
{{Tip|
After it has been created, you should switch to it using
+
* Always commit small changes frequently and with meaningful messages.
 +
* To '''add''' all the modified files to the index, '''and commit''' them in a single command ({{ic|-a}} stands for {{ic|--all}}):
  
  git checkout <branch name>
+
  $ git commit -am "''First commit.''"
 +
}}
  
A simpler method is to do both in one step with
+
'''Edit''' the commit message for the last commit. This also amends the commit with any files which have been newly staged:
  
  git checkout -b <branch name>
+
  $ git commit --amend -m "''Message.''"
  
To see a list of branches, and which branch is currently checked out, use
+
Many of the commands in this article take commits as arguments. A commit can be identified by any of the following:
 
+
git branch
+
 
+
===A word on commits===
+
 
+
Many of the following commands take commits as arguments. A commit can be identified by any of the following:
+
  
 
* Its 40-digit SHA-1 hash (the first 7 digits are usually sufficient to identify it uniquely)
 
* Its 40-digit SHA-1 hash (the first 7 digits are usually sufficient to identify it uniquely)
 
* Any commit label such as a branch or tag name
 
* Any commit label such as a branch or tag name
* The label {{ic|HEAD}} always refers to the currently checked-out commit (usually the head of the branch, unless you used {{ic|git checkout}} to jump back in history to an old commit)
+
* The label {{ic|HEAD}} always refers to the currently checked-out commit (usually the head of the branch, unless you used ''git checkout'' to jump back in history to an old commit)
 
* Any of the above plus {{ic|~}} to refer to previous commits. For example, {{ic|HEAD~}} refers to one commit before {{ic|HEAD}} and {{ic|HEAD~5}} refers to five commits before {{ic|HEAD}}.
 
* Any of the above plus {{ic|~}} to refer to previous commits. For example, {{ic|HEAD~}} refers to one commit before {{ic|HEAD}} and {{ic|HEAD~5}} refers to five commits before {{ic|HEAD}}.
  
===Commits as checkpoints===
+
==== View changes ====
  
In Subversion and other older, centralized version control systems, commits are permanent - once you make them,
+
'''Show differences''' between commits:
they are there on the server for everyone to see.
+
In Git, your commits are local and you can combine, rearrange, and edit them before pushing them to the server.
+
This gives you more flexibility and lets you use commits as checkpoints. Commit early and commit often.
+
  
===Editing the previous commit===
+
$ git diff HEAD HEAD~3
  
git commit --amend
+
or between staging area and working tree:
  
allows you to modify the previous commit. The contents of the index will be applied to it,
+
$ git diff
allowing you to add more files or changes you forgot to put in. You can also use it to edit the commit message,
+
if you would like.
+
  
===Squashing, rearranging, and changing history===
+
'''Get''' a general '''overview''' of the changes:
  
  git rebase -i <commit>
+
  $ git status
  
will bring up a list of all commits between {{ic|<commit>}} and the present, including {{ic|HEAD}} but excluding {{ic|<commit>}}.
+
'''View history''' of changes (where "''-N''" is the number of latest commits):
This command allows you rewrite history. To the left of each commit, a command is specified.
+
Your options are as follows:
+
  
* The "pick" command (the default) uses that commit in the rewritten history.
+
$ git log -p ''(-N)''
* The "reword" command lets you change a commit message without changing the commit's contents.
+
* The "edit" command will cause Git to pause during the history rewrite at this commit. You can then modify it with {{ic|git commit --amend}} or insert new commits.
+
* The "squash" command will cause a commit to be folded into the previous one. You will be prompted to enter a message for the combined commit.
+
* The "fixup" command works like squash, but discards the message of the commit being squashed instead of prompting for a new message.
+
* Commits can be erased from history by deleting them from the list of commits
+
* Commits can be re-ordered by re-ordering them in the list. When you are done modifying the list, Git will prompt you to resolve any resulting merge problems (after doing so, continue rebasing with {{ic|git rebase --continue}})
+
  
When you are done modifying the list, Git will perform the desired actions.
+
==== Branch a repository ====
If Git stops at a commit (due to merge conflicts caused by re-ordering the commits or due to the "edit" command),
+
use {{ic|git rebase --continue}} to resume. You can always back out of the rebase operation with {{ic|git rebase --abort}}.
+
  
{{warning|Only use {{ic|git rebase -i}} on local commits that have not yet been pushed to anybody else.
+
Fixes and new features are usually tested in branches. When changes are satisfactory they can merged back into the default (master) branch.
Modifying commits that are on the central server will cause merge problems for obvious reasons.}}
+
  
{{note|Vim makes these rebase operations very simple since lines can be cut and pasted with few keystrokes.}}
+
'''Create''' a branch, whose name accurately reflects its purpose:
  
==Git Prompt==
+
$ git branch ''help-section-addition''
The Git package comes with a prompt script. To enable the prompt addition you will need to source the git-prompt.sh script and add {{Ic|$(__git_ps1 " (%s)")}} to your PS1 variable.
+
* Add the following line to your {{ic|~/.bashrc}}/{{ic|~/.zshrc}}:
+
source /usr/share/git/completion/git-prompt.sh
+
* For Bash:
+
PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
+
{{Note|For information about coloring your Bash prompt, see [[Color_Bash_Prompt]]}}
+
{{Note|For information about coloring your Git prompt, see [[#Colors in Git Prompt]]}}
+
  
* For zsh:
+
'''List''' branches:
PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
+
  
The {{Ic|%s}} is replaced by the current branch name. Git information is displayed only if you are navigating in a Git repository. You can enable extra information by setting and exporting certain variables to a non-empty value as shown in the following table:
+
$ git branch
  
{| border="1"
+
'''Switch''' branches:
|+
+
! Variable !! Information
+
|-
+
| GIT_PS1_SHOWDIRTYSTATE || '''*''' for unstaged and '''+''' for staged changes
+
|-
+
| GIT_PS1_SHOWSTASHSTATE || '''$''' if something is stashed
+
|-
+
| GIT_PS1_SHOWUNTRACKEDFILES || '''%''' if there are untracked files
+
|}
+
  
In addition you can set the {{Ic|GIT_PS1_SHOWUPSTREAM}} variable to {{Ic|"auto"}} in order to see {{Ic|'''<'''}} if you are behind upstream, {{Ic|'''>'''}} if you are ahead and {{Ic|'''<>'''}} if you have diverged.
+
$ git checkout ''branch''
  
{{Note|If you experience that {{Ic|$(__git_ps1)}} returns {{Ic|((unknown))}}, then there's a {{Ic|.git}} folder in your current directory which doesn't contain any repository, and therefore Git does not recognize it. This can for example happen if you for some reason mistake Git's config-file to be {{Ic|~/.git/config}} instead of {{Ic|~/.gitconfig}}.}}
+
'''Create and switch''':
  
==Transfer Protocols==
+
$ git checkout -b ''branch''
===Smart HTTP===
+
Since version 1.6.6 git is able to use the HTTP(S) protocol as efficiently as SSH or Git by utilizing the git-http-backend. Furthermore it is not only possible to clone or pull from repositories, but also to push into repositories over HTTP(S).
+
  
The setup for this is rather simple as all you need to have installed is the Apache web server (with mod_cgi, mod_alias, and mod_env enabled) and of course, git:
+
'''Merge''' a branch back to the master branch:
# pacman -S apache git
+
  
Once you have your basic setup up and running, add the following to your Apache's config usually located at {{ic|/etc/httpd/conf/httpd.conf}}:
+
$ git checkout master
<Directory "/usr/lib/git-core*">
+
$ git merge ''branch''
    Order allow,deny
+
 
    Allow from all
+
The changes will be merged if they do not conflict. Otherwise, Git will print an error message, and annotate files in the working tree to record the conflicts. The annotations can be displayed with {{ic|git diff}}. Conflicts are resolved by editing the files to remove the annotations, and committing the final version. See [[#Dealing with merges]] below.
</Directory>
+
 
 +
When done with a branch, '''delete''' it with:
 +
 
 +
$ git branch -d ''branch''
 +
 
 +
=== Collaboration ===
 +
 
 +
==== Adopting a good etiquette ====
 +
 
 +
* When considering contributing to an existing project, read and understand its license, as it may excessively limit your ability to change the code. Some licenses can generate disputes over the ownership of the code.
 +
* Think about the project's community and how well you can fit into it. To get a feeling of the direction of the project, read any documentation and even the [[#History and versioning|log]] of the repository.
 +
* When requesting to pull a commit, or submit a patch, keep it small and well documented; this will help the maintainers understand your changes and decide whether to merge them or ask you to make some amendments.
 +
* If a contribution is rejected, do not get discouraged, it is their project after all. If it is important, discuss the reasoning for the contribution as clearly and as patiently as possible: with such an approach a resolution may eventually be possible.
 +
 
 +
==== Clone a repository ====
 +
 
 +
To begin contributing to a project, '''clone''' its repository:
 +
 
 +
$ git clone ''location'' ''folder''
 +
 
 +
{{ic|''location''}} can be either a path or network address. Also, when cloning is done, the location is recorded so just a {{ic|git pull}} will be needed later.
 +
 
 +
==== Pull requests ====
 +
 
 +
After making and committing some changes, the contributor can ask the original author to merge them. This is called a ''pull request''.
 +
 
 +
To '''pull''':
 +
 
 +
$ git pull ''location'' master
 +
 
 +
The ''pull'' command combines both ''fetching'' and ''merging''. If there are conflicts (e.g. the original author made changes in the same time span), then it will be necessary to manually fix them.
 +
 
 +
Alternatively, the original author can '''pick''' the '''changes''' wanting to be incorporated. Using the ''fetch'' option (and ''log'' option with a special {{ic|FETCH_HEAD}} symbol), the contents of the pull request can be viewed before deciding what to do:
 +
 
 +
$ git fetch ''location'' master
 +
$ git log -p HEAD..FETCH_HEAD
 +
$ git merge ''location'' master
 +
 
 +
==== Using remotes ====
 +
 
 +
Remotes are aliases for tracked remote repositories. A ''label'' is created defining a location. These labels are used to identify frequently accessed repositories.
 +
 
 +
'''Create''' a remote:
 +
 
 +
$ git remote add ''label'' ''location''
 +
 
 +
'''Fetch''' a remote:
 +
 
 +
$ git fetch ''label''
 +
 
 +
'''Show differences''' between master and a remote master:
 +
 
 +
$ git log -p master..''label''/master
 +
 
 +
'''View''' remotes for the current repository:
 +
 
 +
$ git remote -v
 +
 
 +
When defining a remote that is a parent of the fork (the project lead), it is defined as ''upstream''.
 +
 
 +
==== Push to a repository ====
 +
 
 +
After being given rights from the original authors, '''push''' changes with:
 +
 
 +
$ git push ''location'' ''branch''
 +
 
 +
When ''git clone'' is performed, it records the original location and gives it a remote name of {{ic|origin}}.
 +
 
 +
So what '''typically''' is done is this:
 +
 
 +
$ git push origin master
 +
 
 +
If the {{ic|-u}} ({{ic|--set-upstream-to}}) option is used, the location is recorded so the next time just a {{ic|git push}} is necessary.
 +
 
 +
==== Dealing with merges ====
 +
 
 +
See [http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging#Basic-Merge-Conflicts Basic Merge Conflicts] in the Git Book for a detailed explanation on how to resolve merge conflicts. Merges are generally reversible. If wanting to back out of a merge one can usually use the {{ic|--abort}} command (e.g. {{ic|git merge --abort}} or {{ic|git pull --abort}}).
 +
 
 +
==== Send patch to mailing list ====
 +
 
 +
If you want to send patches directly to a mailing list, you have to install the following packages: {{Pkg|perl-authen-sasl}}, {{Pkg|perl-net-smtp-ssl}} and {{Pkg|perl-mime-tools}}.
 +
 
 +
Make sure you have configured you username and e-mail address, see [[#Configuration]].
 +
 
 +
'''Configure''' your '''e-mail''' settings:
 +
 
 +
$ git config --global sendemail.smtpserver ''smtp.gmail.com''
 +
$ git config --global sendemail.smtpserverport ''587''
 +
$ git config --global sendemail.smtpencryption ''tls''
 +
$ git config --global sendemail.smtpuser ''foobar@gmail.com''
 +
 
 +
Now you should be able to '''send''' the '''patch''' to the mailing list (see also [http://www.openembedded.org/wiki/How_to_submit_a_patch_to_OpenEmbedded#Sending_patches OpenEmbedded:How to submit a patch to OpenEmbedded#Sending patches]):
 +
 
 +
$ git add ''filename''
 +
$ git commit -s
 +
$ git send-email --to=''openembedded-core@lists.openembedded.org'' --confirm=always -M -1
 +
 
 +
=== History and versioning ===
 +
 
 +
==== Searching the history ====
 +
 
 +
{{ic|git log}} will give the history with a commit checksum, author, date, and the short message. The ''checksum'' is the "object name" of a commit object, typically a 40-character SHA-1 hash.
 +
 
 +
For '''history''' with a '''long message''' (where the "''checksum''" can be truncated, as long as it is unique):
 +
 
 +
$ git show (''checksum'')
 +
 
 +
'''Search''' for ''pattern'' in tracked files:
 +
 
 +
$ git grep ''pattern''
 +
 
 +
'''Search''' in '''{{ic|.c}}''' and '''{{ic|.h}}''' files:
 +
 
 +
$ git grep ''pattern'' -- '*.[ch]'
 +
 
 +
==== Versioning for release ====
 +
 
 +
'''Tag''' commits for versioning:
 +
 
 +
$ git tag 2.14 ''checksum''
 +
 
 +
''Tagging'' is generally done for [https://www.drupal.org/node/1066342 releasing/versioning] but it can be any string. Generally annotated tags are used, because they get added to the Git database.
 +
 
 +
'''Tag''' the '''current''' commit with:
 +
 
 +
$ git tag -a 2.14 -m "Version 2.14"
 +
 
 +
'''List''' tags:
 +
 
 +
$ git tag -l
 +
 
 +
'''Delete''' a tag:
 +
 
 +
$ git tag -d 2.08
 +
 
 +
'''Update remote''' tags:
 +
 
 +
$ git push --tags
 +
 
 +
==== Organizing commits ====
 +
 
 +
Before submitting a pull request it may be desirable to '''consolidate/organize''' the commits. This is done with the ''git rebase'' {{ic|--interactive}} option:
 +
 
 +
$ git rebase -i ''checksum''
 +
 
 +
This will open the editor with a summary of all the commits in the range specified; in this case including the newest ({{ic|HEAD}}) back to, but excluding, commit {{ic|''checksum''}}. Or to use a number notation, use for example {{ic|HEAD~3}}, which will rebase the last three commits:
 +
 
 +
pick d146cc7 Mountpoint test.
 +
pick 4f47712 Explain -o option in readme.
 +
pick 8a4d479 Rename documentation.
 +
 
 +
Editing the action in the first column will dictate how the rebase will be done. The options are:
 +
 
 +
* {{ic|pick}} — Apply this commit as is (the default).
 +
* {{ic|edit}} — Edit files and/or commit message.
 +
* {{ic|reword}} — Edit commit message.
 +
* {{ic|squash}} — Merge/fold into previous commit.
 +
* {{ic|fixup}} — Merge/fold into previous commit discarding its message.
 +
 
 +
The commits can be re-ordered or erased from the history (but be very careful with these). After editing the file, Git will perform the specified actions; if prompted to resolve merge problems, fix them and continue with {{ic|git rebase --continue}} or back out with the {{ic|git rebase --abort}} command.
 +
 
 +
{{Note|Squashing commits is only used for local commits, it will cause troubles on a repository that is shared by other people.}}
 +
 
 +
== Tips and tricks ==
 +
 
 +
=== Using git-config ===
 +
 
 +
Git reads its configuration from a few INI-type configuration files:
 +
 
 +
* Each repository contains a {{ic|.git/config}} file for specific configuration.
 +
* Each user has a {{ic|$HOME/.gitconfig}} file for fallback values.
 +
* {{ic|/etc/gitconfig}} is used for system-wide defaults.
 +
 
 +
These files can be edited directly, but the usual method is to use ''git config'', as shown in the examples below.
 +
 
 +
List the currently set variables:
 +
 
 +
$ git config {--local,--global,--system} --list
 +
 
 +
Set the default editor from [[vim]] to [[nano]]:
 +
 
 +
$ git config --global core.editor "nano -w"
 +
 
 +
Set the default push action:
 +
 
 +
$ git config --global push.default simple
 +
 
 +
Set a different tool for ''git difftool'' (''meld'' by default):
 +
 
 +
$ git config --global diff.tool vimdiff
 +
 
 +
See [https://www.kernel.org/pub/software/scm/git/docs/git-config.html git-config(1)] and [http://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration Git Configuration] for more information.
 +
 
 +
=== Speeding up authentication ===
 +
 
 +
You may wish to avoid the hassle of authenticating interactively at every push to the Git server.
 +
 
 +
* If you are authenticating with SSH keys, use an [[SSH agent]]. See also [[SSH#Speeding up SSH]] and [[SSH#Keep alive]].
 +
* If you are authenticating with username and password, switch to [[SSH keys]] if the server supports SSH, otherwise try [https://git-scm.com/docs/git-credential-cache git-credential-cache] or [https://git-scm.com/docs/git-credential-store git-credential-store].
 +
 
 +
=== Protocol Defaults ===
 +
 
 +
If you are running a multiplexed SSH connection as shown above, Git over SSH might be faster than HTTPS. Also, some servers (like the AUR) only allow pushing via SSH. For example, the following config will set Git over SSH for any repository hosted on the AUR.
 +
 
 +
{{hc|~/.gitconfig|<nowiki>
 +
[url "ssh://aur@aur.archlinux.org/"]
 +
insteadOf &#61; https://aur.archlinux.org/
 +
insteadOf &#61; http://aur.archlinux.org/
 +
insteadOf &#61; git://aur.archlinux.org/
 +
</nowiki>}}
 +
 
 +
=== Bash completion ===
 +
 
 +
In order to enable Bash completion, source {{ic|/usr/share/git/completion/git-completion.bash}} in a [[Bash#Configuration_files|Bash startup file]]. Alternatively, install {{pkg|bash-completion}}.
 +
 
 +
=== Git prompt ===
 +
 
 +
The Git package comes with a prompt script. To enable it, source the {{ic|/usr/share/git/completion/git-prompt.sh}} script in a [[Autostarting#Shells|shell startup file]], then set a custom prompt with the {{ic|%s}} parameter:
 +
 
 +
* For [[Bash]]: {{ic|1=PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '}}
 +
* For [[zsh]]: {{ic|1=PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '}}
 +
 
 +
When changing to a directory of a Git repository, the prompt will change to show the branch name. Extra details can be set to be shown by the prompt:
 +
 
 +
{| class="wikitable"
 +
|+
 +
! Shell variable !! Information
 +
|-
 +
| GIT_PS1_SHOWDIRTYSTATE    || '''+''' for staged, '''*''' if unstaged.
 +
|-
 +
| GIT_PS1_SHOWSTASHSTATE    || '''$''' if something is stashed.
 +
|-
 +
| GIT_PS1_SHOWUNTRACKEDFILES || '''%''' if there are untracked files.
 +
|-
 +
| GIT_PS1_SHOWUPSTREAM      || '''<,>,<>''' behind, ahead, or diverged from upstream.
 +
|}
 +
 
 +
{{ic|GIT_PS1_SHOWUPSTREAM}} will need to be set to {{ic|auto}} for changes to take effect.
 +
 
 +
{{Note|If you experience that {{ic|$(__git_ps1)}} returns {{ic|((unknown))}}, then there is a {{ic|.git}} folder in your current directory which does not contain any repository, and therefore Git does not recognize it. This can, for example, happen if you mistake Git's configuration file to be {{ic|~/.git/config}} instead of {{ic|~/.gitconfig}}.}}
 +
 
 +
Alternatively, you can use one of git shell prompt customization packages from [[AUR]] such as {{AUR|bash-git-prompt}} or {{AUR|gittify}}.
 +
 
 +
=== Visual representation ===
 +
 
 +
To get an idea of the amount of work done:
 +
 
 +
$ git diff --stat
 +
 
 +
''git log'' with forking representation:
 +
 
 +
$ git log --graph --oneline --decorate
 +
 
 +
''git log'' graph alias (i.e. ''git graph'' will show a decorated version):
 +
 
 +
$ git config --global alias.graph 'log --graph --oneline --decorate'
 +
 
 +
=== Commit tips ===
 +
 
 +
Reset to previous commit (very dangerous, erases everything to specified commit):
 +
 
 +
$ git reset --hard HEAD^
 +
 
 +
If a repository address gets changed, its remote location will need to be updated:
 +
 
 +
$ git remote set-url origin git@''address'':''user''/''repo''.git
 +
 
 +
Signed-off-by line append (a name-email signature is added to the commit which is required by some projects):
 +
 
 +
  $ git commit -s
 +
 
 +
Signed-off-by automatically append to patches (when using {{ic|git format-patch ''commit''}}):
 +
 
 +
$ git config --local format.signoff true
 +
 
 +
Commit specific parts of files that have changed. This is useful if there are a large number of changes made that would be best split into several commits:
 +
 
 +
$ git add -p
 +
 
 +
=== Working with a non-master branch ===
 +
 
 +
Occasionally a maintainer will ask that work be done on a branch. These branches are often called {{ic|devel}} or {{ic|testing}}. Begin by cloning the repository.
 +
 
 +
To enter another branch beside master (''git clone'' only shows master branch but others still exist, {{ic|git branch -a}} to show):
 +
 
 +
$ git checkout -b ''branch'' origin/''branch''
 +
 
 +
Now edit normally; however to keep the repository tree in sync be sure to use both:
 +
 
 +
$ git pull --all
 +
$ git push --all
 +
 
 +
== Git server ==
 +
 
 +
How to set up connecting to repositories using varying protocols.
 +
 
 +
=== SSH ===
 +
 
 +
To use the SSH protocol, first set up a public SSH key; for that follow the guide at [[SSH keys]]. To set up a SSH server, follow the [[SSH]] guide.
 +
 
 +
With SSH working and a key generated, paste the contents of {{ic|~/.ssh/id_rsa.pub}} to {{ic|~/.ssh/authorized_keys}} (be sure it is all on one line). Now the Git repository can be accessed with SSH by doing:
 +
 
 +
$ git clone ''user''@''foobar.com'':''my_repository''.git
 +
 
 +
You should now get an SSH yes/no question, if you have the SSH client setting {{ic|StrictHostKeyChecking}} set to {{ic|ask}} (the default). Type {{ic|yes}} followed by {{ic|Enter}}. Then you should have your repository checked out. Because this is with SSH, you also have commit rights now.
 +
 
 +
To modify an existing repository to use SSH, the remote location will need to be redefined:
 +
 
 +
$ git remote set-url origin git@localhost:''my_repository''.git
 +
 
 +
Connecting on a port other than 22 can be configured on a per-host basis in {{ic|/etc/ssh/ssh_config}} or {{ic|~/.ssh/config}}. To set up ports for a repository (here 443 as example):
 +
 
 +
{{hc|.git/config|2=
 +
[remote "origin"]
 +
    url = ssh://''user''@''foobar''.com:443/~''my_repository''/repo.git
 +
}}
 +
 
 +
=== Smart HTTP ===
 +
 
 +
Git is able to use the HTTP(S) protocol as efficiently as the SSH or Git protocols, by utilizing the git-http-backend. Furthermore it is not only possible to clone or pull from repositories, but also to push into repositories over HTTP(S).
 +
 
 +
The setup for this is rather simple as all you need to have installed is the Apache web server ({{pkg|apache}}, with {{ic|mod_cgi}}, {{ic|mod_alias}}, and {{ic|mod_env}} enabled) and of course, {{pkg|git}}.
 +
 
 +
Once you have your basic setup running, add the following to your Apache configuration file, which is usually located at:
 +
 
 +
{{hc|/etc/httpd/conf/httpd.conf|
 +
<Directory "/usr/lib/git-core*">
 +
    Require all granted
 +
</Directory>
 
   
 
   
SetEnv GIT_PROJECT_ROOT /srv/git
+
SetEnv GIT_PROJECT_ROOT /srv/git
SetEnv GIT_HTTP_EXPORT_ALL
+
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
+
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
 +
}}
  
The above example config assumes that your git repositories are located at {{ic|/srv/git}} and that you want to access them via something like <nowiki>http(s)://your_address.tld/git/your_repo.git</nowiki>. Feel free to customize this to your needs.
+
This assumes your Git repositories are located at {{ic|/srv/git}} and that you want to access them via something like: {{ic|<nowiki>http(s)://your_address.tld/git/your_repo.git</nowiki>}}.
  
{{Note|Of course you have to make sure that your Apache can read and write (if you want to enable push access) on your git repositories.}}
+
{{Note|Make sure that Apache can read and write to your repositories.}}
  
 
For more detailed documentation, visit the following links:
 
For more detailed documentation, visit the following links:
Line 267: Line 523:
 
* https://www.kernel.org/pub/software/scm/git/docs/v1.7.10.1/git-http-backend.html
 
* https://www.kernel.org/pub/software/scm/git/docs/v1.7.10.1/git-http-backend.html
  
===Git SSH===
+
=== Git ===
You first need to have a public SSH key. For that follow the guide at [[Using SSH Keys]]. To set up SSH itself, you need to follow the [[SSH]] guide. This assumes you have a public SSH key now and that your SSH is working.
+
Open your SSH key in your favorite editor (default public key name is {{ic|~/.ssh/id_rsa.pub}}), and copy its content ({{ic|Ctrl+c}}).
+
Now go to your user where you have made your Git repository, since we now need to allow that SSH key to log in on that user to access the Git repository.
+
Open {{ic|~/.ssh/authorized_keys}} in your favorite editor, and paste the contents of id_rsa.pub in it. Be sure it is all on one line! That is important! It should look somewhat like this:
+
{{Warning|Do not copy the line below! It is an example! It will not work if you use that line!}}
+
<pre style='overflow:auto'>
+
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCboOH6AotCh4OcwJgsB4AtXzDo9Gzhl+BAHuEvnDRHNSYIURqGN4CrP+b5Bx/iLrRFOBv58TcZz1jyJ2PaGwT74kvVOe9JCCdgw4nSMBV44cy+6cTJiv6f1tw8pHRS2H6nHC9SCSAWkMX4rpiSQ0wkhjug+GtBWOXDaotIzrFwLw== username@hostname
+
</pre>
+
Now you can checkout your Git repository this way (change where needed. Here it is using the git username and localhost):
+
git clone git@localhost:my_repository.git
+
You should now get an SSH yes/no question. Type {{ic|yes}} followed by {{ic|Enter}}. Then you should have your repository checked out. Because this is with SSH, you also do have commit rights now. For that look at [[Git]] and [[Super Quick Git Guide]].
+
  
====Specifying a non-standard port====
+
{{Note|The Git protocol is not encrypted or authenticated, and only allows read access.}}
Connecting on a port other than 22 can be configured on a per-host basis in {{ic|/etc/ssh/ssh_config}} or {{ic|~/.ssh/config}}. To set up ports for a repository, specify the path in {{ic|.git/config}} using the port number {{ic|N}} and the ''absolute path'' {{ic|/PATH/TO/REPO}}:
+
ssh://user@example.org:N/PATH/TO/REPO
+
Typically the repository resides in the home directory of the user which allows you to use tilde-expansion. Thus to connect on port N=443,
+
url = git@example.org:repo.git
+
becomes:
+
url = ssh://git@example.org:443/~git/repo.git
+
  
===Git daemon===
+
[[start|Start and enable]] {{ic|git-daemon.socket}}.
{{Note|The git daemon only allows read access. For write access see [[#Git SSH]].}}
+
This will allow URLs like "git clone git://localhost/my_repository.git".
+
  
Start git-daemon with root privileges.
+
The daemon is started with the following options:
# systemctl start git-daemon.socket
+
  
To run the git-daemon every time at boot, enable the service:
 
# systemctl enable git-daemon.socket
 
 
The daemon is started with the following parameters which are placed in the systemd service file.
 
 
  ExecStart=-/usr/lib/git-core/git-daemon --inetd --export-all --base-path=/srv/git
 
  ExecStart=-/usr/lib/git-core/git-daemon --inetd --export-all --base-path=/srv/git
  
So you have to place your repositories in /srv/git/ to be able to clone them with git daemon.
+
Repositories placed in {{ic|/srv/git/}} will be recognized by the daemon.  Clients can connect with something similar to:
 +
 
 +
$ git clone git://''location''/''repository''.git
 +
 
 +
=== Setting access rights ===
  
Clients can now simply use:
+
To restrict read and/or write access, use standard Unix permissions. Refer to http://sitaramc.github.com/gitolite/doc/overkill.html{{Dead link|2013|11|06}} ([https://web.archive.org/web/20111004134500/http://sitaramc.github.com/gitolite/doc/overkill.html archive.org mirror]) for more information.
git clone git://localhost/my_repository.git
+
  
=== Git repositories rights ===
+
For fine-grained access management, refer to [[gitolite]] and [[gitosis]].
To restrict read/write access, you can simply use Unix rights, see http://sitaramc.github.com/gitolite/doc/overkill.html
+
  
For a fine-grained rights access, see [[gitolite]] and [[gitosis]]
+
== See also ==
  
==See also==
+
* Miscallaneous man pages available in the {{Pkg|git}} package: {{ic|gittutorial(7)}}, {{ic|giteveryday(7)}}, {{ic|gitworkflows(7)}}
 
* [http://git-scm.com/book Pro Git book]
 
* [http://git-scm.com/book Pro Git book]
 
* [http://gitref.org/ Git Reference]
 
* [http://gitref.org/ Git Reference]
 
* https://www.kernel.org/pub/software/scm/git/docs/
 
* https://www.kernel.org/pub/software/scm/git/docs/
* https://help.github.com/
+
* [https://gun.io/blog/how-to-github-fork-branch-and-pull-request Git overall]
 +
* [http://nathanhoad.net/git-workflow-forks-remotes-and-pull-requests Git overall2]
 +
* https://wiki.videolan.org/Git
 +
* [https://gist.github.com/grawity/4392747 A comparison of protocols offered by GitHub]

Latest revision as of 02:35, 24 July 2016


I've met people who thought that git is a front-end to GitHub. They were wrong, git is a front-end to AUR.
— Linus Torvalds


Git is the version control system (VCS) designed and developed by Linus Torvalds, the creator of the Linux kernel. Git is now used to maintain AUR packages, as well as many other projects, including sources for the Linux kernel.

Installation

Install the git package. For the development version, install git-gitAUR from the AUR. Check the optional dependencies when using tools such as git svn, git gui and gitk.

Note: To enable spell checking in git-gui, aspell is required, along with the dictionary corresponding to the LC_MESSAGES environment variable. See FS#28181 and the aspell article.

Configuration

In order to use Git you need to set at least a name and email:

$ git config --global user.name  "John Doe"
$ git config --global user.email "johndoe@foobar.com"

See #Tips and tricks for more settings.

Usage

This tutorial teaches how to use Git for basic distributed revision control of a project.

Git is a distributed version control system, which means that the entire history of changes to a repository is stored locally, in a directory called ./.git in the project directory. The project files which are visible to the user constitute the working tree. These files can be updated to match revisions stored in ./.git using git commands (e.g. git checkout), and new revisions can be created in turn by editing these files and running the appropriate git commands (e.g. git commit).

See man gitglossary for more complete definitions of the terms used in this tutorial.

A typical Git work-flow is:

  1. Create a new project or clone a remote one.
  2. Create a branch to make changes; then commit those changes.
  3. Consolidate commits for better organization/understanding.
  4. Merge commits back into the main branch.
  5. (Optional) Push changes to a remote server.

Local repository

Staging operations

Initialize a new repository. This creates and initializes ./.git:

$ cd (your project)/
$ git init

To record the changes to the repository, they must first be added to the index, or staging area, with an operation often also referred to as staging. When you commit changes using git commit, it is the contents of the index which are committed to the current branch, not the contents of the working tree.

Note: The index is actually a binary file .git/index, which can be queried with git ls-files --stage.

To add files to the index from the working tree:

$ git add file1 file2

This records the current state of the files. If the files are subsequently modified, you can run git add again to "add" the new versions to the index.

Add all files:

$ git add .
Tip: To ignore some files from, e.g. git add ., create a .gitignore file (or files):
.gitignore
# File I'll likely delete
test-script

# Ignore all .html files, except 'important.html'
*.html
!important.html

# Ignore all files recursively in 'DoNotInclude'
DoNotInclude/**

See gitignore(5) for details.

Remove a file from staging (--cached preserves the actual file(s)):

$ git rm (--cached) file

Remove all files:

$ git rm --cached -r .

Or:

$ git reset HEAD -- .

Here, HEAD is a "symbolic reference" to the current revision.

Rename a file:

$ git mv file1 file2
Note: git mv is a convenience command, roughly equivalent to mv file1 file2 followed by git rm file1 and git add file2. Rename detection during merges is based only on content similarity, and ignores the actual commands used to rename files. The broader rationale for this approach, which distinguishes Git from patch-based systems like Darcs, can be found here.

List files:

$ git ls-files

By default this shows files in the staging area (--cached files).

Commit changes

Once the content to be recorded is staged, commit them with:

$ git commit -m "First commit."

The -m (--message) option is for a short message: if omitted, the preset editor will be spawned to allow entering a longer message.

Tip:
  • Always commit small changes frequently and with meaningful messages.
  • To add all the modified files to the index, and commit them in a single command (-a stands for --all):
$ git commit -am "First commit."

Edit the commit message for the last commit. This also amends the commit with any files which have been newly staged:

$ git commit --amend -m "Message."

Many of the commands in this article take commits as arguments. A commit can be identified by any of the following:

  • Its 40-digit SHA-1 hash (the first 7 digits are usually sufficient to identify it uniquely)
  • Any commit label such as a branch or tag name
  • The label HEAD always refers to the currently checked-out commit (usually the head of the branch, unless you used git checkout to jump back in history to an old commit)
  • Any of the above plus ~ to refer to previous commits. For example, HEAD~ refers to one commit before HEAD and HEAD~5 refers to five commits before HEAD.

View changes

Show differences between commits:

$ git diff HEAD HEAD~3

or between staging area and working tree:

$ git diff

Get a general overview of the changes:

$ git status

View history of changes (where "-N" is the number of latest commits):

$ git log -p (-N)

Branch a repository

Fixes and new features are usually tested in branches. When changes are satisfactory they can merged back into the default (master) branch.

Create a branch, whose name accurately reflects its purpose:

$ git branch help-section-addition

List branches:

$ git branch

Switch branches:

$ git checkout branch

Create and switch:

$ git checkout -b branch

Merge a branch back to the master branch:

$ git checkout master
$ git merge branch

The changes will be merged if they do not conflict. Otherwise, Git will print an error message, and annotate files in the working tree to record the conflicts. The annotations can be displayed with git diff. Conflicts are resolved by editing the files to remove the annotations, and committing the final version. See #Dealing with merges below.

When done with a branch, delete it with:

$ git branch -d branch

Collaboration

Adopting a good etiquette

  • When considering contributing to an existing project, read and understand its license, as it may excessively limit your ability to change the code. Some licenses can generate disputes over the ownership of the code.
  • Think about the project's community and how well you can fit into it. To get a feeling of the direction of the project, read any documentation and even the log of the repository.
  • When requesting to pull a commit, or submit a patch, keep it small and well documented; this will help the maintainers understand your changes and decide whether to merge them or ask you to make some amendments.
  • If a contribution is rejected, do not get discouraged, it is their project after all. If it is important, discuss the reasoning for the contribution as clearly and as patiently as possible: with such an approach a resolution may eventually be possible.

Clone a repository

To begin contributing to a project, clone its repository:

$ git clone location folder

location can be either a path or network address. Also, when cloning is done, the location is recorded so just a git pull will be needed later.

Pull requests

After making and committing some changes, the contributor can ask the original author to merge them. This is called a pull request.

To pull:

$ git pull location master

The pull command combines both fetching and merging. If there are conflicts (e.g. the original author made changes in the same time span), then it will be necessary to manually fix them.

Alternatively, the original author can pick the changes wanting to be incorporated. Using the fetch option (and log option with a special FETCH_HEAD symbol), the contents of the pull request can be viewed before deciding what to do:

$ git fetch location master
$ git log -p HEAD..FETCH_HEAD
$ git merge location master

Using remotes

Remotes are aliases for tracked remote repositories. A label is created defining a location. These labels are used to identify frequently accessed repositories.

Create a remote:

$ git remote add label location

Fetch a remote:

$ git fetch label

Show differences between master and a remote master:

$ git log -p master..label/master

View remotes for the current repository:

$ git remote -v

When defining a remote that is a parent of the fork (the project lead), it is defined as upstream.

Push to a repository

After being given rights from the original authors, push changes with:

$ git push location branch

When git clone is performed, it records the original location and gives it a remote name of origin.

So what typically is done is this:

$ git push origin master

If the -u (--set-upstream-to) option is used, the location is recorded so the next time just a git push is necessary.

Dealing with merges

See Basic Merge Conflicts in the Git Book for a detailed explanation on how to resolve merge conflicts. Merges are generally reversible. If wanting to back out of a merge one can usually use the --abort command (e.g. git merge --abort or git pull --abort).

Send patch to mailing list

If you want to send patches directly to a mailing list, you have to install the following packages: perl-authen-sasl, perl-net-smtp-ssl and perl-mime-tools.

Make sure you have configured you username and e-mail address, see #Configuration.

Configure your e-mail settings:

$ git config --global sendemail.smtpserver smtp.gmail.com
$ git config --global sendemail.smtpserverport 587
$ git config --global sendemail.smtpencryption tls
$ git config --global sendemail.smtpuser foobar@gmail.com

Now you should be able to send the patch to the mailing list (see also OpenEmbedded:How to submit a patch to OpenEmbedded#Sending patches):

$ git add filename
$ git commit -s
$ git send-email --to=openembedded-core@lists.openembedded.org --confirm=always -M -1

History and versioning

Searching the history

git log will give the history with a commit checksum, author, date, and the short message. The checksum is the "object name" of a commit object, typically a 40-character SHA-1 hash.

For history with a long message (where the "checksum" can be truncated, as long as it is unique):

$ git show (checksum)

Search for pattern in tracked files:

$ git grep pattern

Search in .c and .h files:

$ git grep pattern -- '*.[ch]'

Versioning for release

Tag commits for versioning:

$ git tag 2.14 checksum

Tagging is generally done for releasing/versioning but it can be any string. Generally annotated tags are used, because they get added to the Git database.

Tag the current commit with:

$ git tag -a 2.14 -m "Version 2.14"

List tags:

$ git tag -l

Delete a tag:

$ git tag -d 2.08

Update remote tags:

$ git push --tags

Organizing commits

Before submitting a pull request it may be desirable to consolidate/organize the commits. This is done with the git rebase --interactive option:

$ git rebase -i checksum

This will open the editor with a summary of all the commits in the range specified; in this case including the newest (HEAD) back to, but excluding, commit checksum. Or to use a number notation, use for example HEAD~3, which will rebase the last three commits:

pick d146cc7 Mountpoint test.
pick 4f47712 Explain -o option in readme.
pick 8a4d479 Rename documentation.

Editing the action in the first column will dictate how the rebase will be done. The options are:

  • pick — Apply this commit as is (the default).
  • edit — Edit files and/or commit message.
  • reword — Edit commit message.
  • squash — Merge/fold into previous commit.
  • fixup — Merge/fold into previous commit discarding its message.

The commits can be re-ordered or erased from the history (but be very careful with these). After editing the file, Git will perform the specified actions; if prompted to resolve merge problems, fix them and continue with git rebase --continue or back out with the git rebase --abort command.

Note: Squashing commits is only used for local commits, it will cause troubles on a repository that is shared by other people.

Tips and tricks

Using git-config

Git reads its configuration from a few INI-type configuration files:

  • Each repository contains a .git/config file for specific configuration.
  • Each user has a $HOME/.gitconfig file for fallback values.
  • /etc/gitconfig is used for system-wide defaults.

These files can be edited directly, but the usual method is to use git config, as shown in the examples below.

List the currently set variables:

$ git config {--local,--global,--system} --list

Set the default editor from vim to nano:

$ git config --global core.editor "nano -w"

Set the default push action:

$ git config --global push.default simple

Set a different tool for git difftool (meld by default):

$ git config --global diff.tool vimdiff

See git-config(1) and Git Configuration for more information.

Speeding up authentication

You may wish to avoid the hassle of authenticating interactively at every push to the Git server.

Protocol Defaults

If you are running a multiplexed SSH connection as shown above, Git over SSH might be faster than HTTPS. Also, some servers (like the AUR) only allow pushing via SSH. For example, the following config will set Git over SSH for any repository hosted on the AUR.

~/.gitconfig
[url "ssh://aur@aur.archlinux.org/"]
	insteadOf = https://aur.archlinux.org/
	insteadOf = http://aur.archlinux.org/
	insteadOf = git://aur.archlinux.org/

Bash completion

In order to enable Bash completion, source /usr/share/git/completion/git-completion.bash in a Bash startup file. Alternatively, install bash-completion.

Git prompt

The Git package comes with a prompt script. To enable it, source the /usr/share/git/completion/git-prompt.sh script in a shell startup file, then set a custom prompt with the %s parameter:

  • For Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
  • For zsh: PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '

When changing to a directory of a Git repository, the prompt will change to show the branch name. Extra details can be set to be shown by the prompt:

Shell variable Information
GIT_PS1_SHOWDIRTYSTATE + for staged, * if unstaged.
GIT_PS1_SHOWSTASHSTATE $ if something is stashed.
GIT_PS1_SHOWUNTRACKEDFILES % if there are untracked files.
GIT_PS1_SHOWUPSTREAM <,>,<> behind, ahead, or diverged from upstream.

GIT_PS1_SHOWUPSTREAM will need to be set to auto for changes to take effect.

Note: If you experience that $(__git_ps1) returns ((unknown)), then there is a .git folder in your current directory which does not contain any repository, and therefore Git does not recognize it. This can, for example, happen if you mistake Git's configuration file to be ~/.git/config instead of ~/.gitconfig.

Alternatively, you can use one of git shell prompt customization packages from AUR such as bash-git-promptAUR or gittifyAUR.

Visual representation

To get an idea of the amount of work done:

$ git diff --stat

git log with forking representation:

$ git log --graph --oneline --decorate

git log graph alias (i.e. git graph will show a decorated version):

$ git config --global alias.graph 'log --graph --oneline --decorate'

Commit tips

Reset to previous commit (very dangerous, erases everything to specified commit):

$ git reset --hard HEAD^

If a repository address gets changed, its remote location will need to be updated:

$ git remote set-url origin git@address:user/repo.git

Signed-off-by line append (a name-email signature is added to the commit which is required by some projects):

 $ git commit -s

Signed-off-by automatically append to patches (when using git format-patch commit):

$ git config --local format.signoff true

Commit specific parts of files that have changed. This is useful if there are a large number of changes made that would be best split into several commits:

$ git add -p

Working with a non-master branch

Occasionally a maintainer will ask that work be done on a branch. These branches are often called devel or testing. Begin by cloning the repository.

To enter another branch beside master (git clone only shows master branch but others still exist, git branch -a to show):

$ git checkout -b branch origin/branch

Now edit normally; however to keep the repository tree in sync be sure to use both:

$ git pull --all
$ git push --all

Git server

How to set up connecting to repositories using varying protocols.

SSH

To use the SSH protocol, first set up a public SSH key; for that follow the guide at SSH keys. To set up a SSH server, follow the SSH guide.

With SSH working and a key generated, paste the contents of ~/.ssh/id_rsa.pub to ~/.ssh/authorized_keys (be sure it is all on one line). Now the Git repository can be accessed with SSH by doing:

$ git clone user@foobar.com:my_repository.git

You should now get an SSH yes/no question, if you have the SSH client setting StrictHostKeyChecking set to ask (the default). Type yes followed by Enter. Then you should have your repository checked out. Because this is with SSH, you also have commit rights now.

To modify an existing repository to use SSH, the remote location will need to be redefined:

$ git remote set-url origin git@localhost:my_repository.git

Connecting on a port other than 22 can be configured on a per-host basis in /etc/ssh/ssh_config or ~/.ssh/config. To set up ports for a repository (here 443 as example):

.git/config
[remote "origin"]
    url = ssh://user@foobar.com:443/~my_repository/repo.git

Smart HTTP

Git is able to use the HTTP(S) protocol as efficiently as the SSH or Git protocols, by utilizing the git-http-backend. Furthermore it is not only possible to clone or pull from repositories, but also to push into repositories over HTTP(S).

The setup for this is rather simple as all you need to have installed is the Apache web server (apache, with mod_cgi, mod_alias, and mod_env enabled) and of course, git.

Once you have your basic setup running, add the following to your Apache configuration file, which is usually located at:

/etc/httpd/conf/httpd.conf
<Directory "/usr/lib/git-core*">
    Require all granted
</Directory>
 
SetEnv GIT_PROJECT_ROOT /srv/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/

This assumes your Git repositories are located at /srv/git and that you want to access them via something like: http(s)://your_address.tld/git/your_repo.git.

Note: Make sure that Apache can read and write to your repositories.

For more detailed documentation, visit the following links:

Git

Note: The Git protocol is not encrypted or authenticated, and only allows read access.

Start and enable git-daemon.socket.

The daemon is started with the following options:

ExecStart=-/usr/lib/git-core/git-daemon --inetd --export-all --base-path=/srv/git

Repositories placed in /srv/git/ will be recognized by the daemon. Clients can connect with something similar to:

$ git clone git://location/repository.git

Setting access rights

To restrict read and/or write access, use standard Unix permissions. Refer to http://sitaramc.github.com/gitolite/doc/overkill.html[dead link 2013-11-06] (archive.org mirror) for more information.

For fine-grained access management, refer to gitolite and gitosis.

See also