diff --git a/Documentation/gittutorial.adoc b/Documentation/gittutorial.adoc index 03120ba19105e8..c8b6f0ebd03304 100644 --- a/Documentation/gittutorial.adoc +++ b/Documentation/gittutorial.adoc @@ -3,668 +3,736 @@ gittutorial(7) NAME ---- -gittutorial - A tutorial introduction to Git +gittutorial - Introduction to Git for beginners DESCRIPTION ----------- -This tutorial explains how to import a new project into Git, make -changes to it, and share changes with other developers. +Git is a program that lets you collaborate with others on code, back up +your code, roll back to an earlier version of your project, track how +your project has changed over time, and much more. -If you are instead primarily interested in using Git to fetch a project, -for example, to test the latest version, you may prefer to start with -the first two chapters of link:user-manual.html[The Git User's Manual]. +This tutorial explains how to create a new Git project, make +changes to it, and upload the project to the Internet. It usually takes +less than an hour if you have a little previous experience with Git, and +1-2 hours if not. -First, note that you can get documentation for a command such as -`git log --graph` with: +We'll show you how to use the commands `git commit`, `git add`, +`git diff`, `git status`, and `git push`. + +What we'll be doing +------------------- + +Git lets you take snapshots of your code, like a checkpoint in a video +game. These snapshots are called "commits". Which files to save in a +commit is up to you. + +When Git stores a commit, it stores a copy of every file in the commit +in a database in a directory called `.git`. This is called a "Git repository". + +In this tutorial we're going to show you how to: + +1. Create a Git repository in a directory with the command `git init`. + This creates the `.git` directory where Git stores all your commits. +2. Tell Git which files you want to put in a commit +3. Make a commit +4. Change a file and make a new commit with the new version +5. Make experimental changes and throw them away + +We'll also explain how to use Git to put your code on the Internet. + +Command line vs graphical interfaces +------------------------------------ + +Git is a command line program, but there are many graphical interfaces +for Git built by the community. Your text editor might even have a +built-in Git integration. + +In this tutorial, we'll give instructions for using Git from the +command line. We can't give you instructions for how to do it in your +graphical interface because there are so many of them. + +You can always switch back and forth between using the command line and +a graphical interface at any time. + +Step 1: Make sure Git is installed +---------------------------------- + +To do this tutorial, you'll need: + +1. Git to be installed. You might already have it installed, + and if not there are directions at https://git-scm.com/install/ +2. A terminal to use. On Windows, you can use Git Bash which comes + when you install Git. + +You can check if Git is installed by running this in your terminal: ------------------------------------------------ -$ man git-log +$ git --version ------------------------------------------------ -or: +It should output something like this: ------------------------------------------------ -$ git help log +git version 2.54.0 ------------------------------------------------ -With the latter, you can use the manual viewer of your choice; see -linkgit:git-help[1] for more information. +The exact version isn't too important: this tutorial is designed to work +with any version of Git after 2.0. -It is a good idea to introduce yourself to Git with your name and -public email address before doing any operation. The easiest -way to do so is: +[[step_2]] +Step 2: Introduce yourself to Git +--------------------------------- + +The first time you use Git on a computer, it's a good idea to tell Git +your name and public email address. If you don't, you'll get a lot of +warnings from Git. To do this, run: ------------------------------------------------ -$ git config --global user.name "Your Name Comes Here" -$ git config --global user.email you@yourdomain.example.com +$ git config --global user.name "Namey McName" +$ git config --global user.email you@example.com ------------------------------------------------ +The name and email is so that other people you're collaborating with +can know who made the changes. You can set them to anything you want. -Importing a new project ------------------------ - -Assume you have a tarball `project.tar.gz` with your initial work. You -can place it under Git revision control as follows. +To check if the name and email have been set, you can run these +commands. They should display your name and email: ------------------------------------------------ -$ tar xzf project.tar.gz -$ cd project -$ git init +$ git config user.name +$ git config user.email ------------------------------------------------ -Git will reply +Next, configure Git to set the default branch name to `main` (instead +of `master`) by running this command. We can't explain what a branch is +yet, but Git is going to +https://sfconservancy.org/news/2020/jun/23/gitbranchname/[make `main` the default soon], +and setting this avoids some extremely annoying problems in Step 14. ------------------------------------------------ -Initialized empty Git repository in .git/ +$ git config --global init.defaultBranch main ------------------------------------------------ -You've now initialized the working directory--you may notice a new -directory created, named `.git`. +If there's no output, then it succeeded. + +[NOTE] +It's also possible to set a different email address for every project, +but we're not covering that here. + +Step 3: Create an empty folder and 1 file +------------------------------------------ -Next, tell Git to take a snapshot of the contents of all files under the -current directory (note the `.`), with `git add`: +In your terminal, create an empty folder and change directories into it. +Later on you could follow the same steps in this tutorial to take an +existing project and start managing it with Git, but we're going to use +an empty project so that everyone following this tutorial has the exact +same files. + +For example, run these commands to make a folder called `myproject` ------------------------------------------------ -$ git add . +$ mkdir myproject +$ cd myproject ------------------------------------------------ -This snapshot is now stored in a temporary staging area which Git calls -the "index". You can permanently store the contents of the index in the -repository with `git commit`: +Next, using your text editor, create a file in this directory, so we +have something to work with. + +Make a file called README.md, with these contents: ------------------------------------------------ -$ git commit +We're doing a Git tutorial! +We need 2 lines in this file so here's a second one ------------------------------------------------ -This will prompt you for a commit message. You've now stored the first -version of your project in Git. - -Making changes --------------- +Save `README.md` and keep it open in your text editor so you can +easily edit it later. The exact contents aren't too important, but +we'll use those contents in the example output later. -Modify some files, then add their updated contents to the index: +You can check that the file is in the right place by running `ls`, +like this: ------------------------------------------------ -$ git add file1 file2 file3 +$ ls ------------------------------------------------ -You are now ready to commit. You can see what is about to be committed -using `git diff` with the `--cached` option: +The output should look like this: ------------------------------------------------ -$ git diff --cached +README.md ------------------------------------------------ -(Without `--cached`, `git diff` will show you any changes that -you've made but not yet added to the index.) You can also get a brief -summary of the situation with `git status`: +Step 4: Create a Git repository +------------------------------- ------------------------------------------------- -$ git status -On branch master -Changes to be committed: - (use "git restore --staged ..." to unstage) +A Git repository lets you save snapshots of your code. Every time you make a +snapshot, Git stores a copy of the contents of every file in the snapshot. - modified: file1 - modified: file2 - modified: file3 +This might feel unbelievable, but Git uses compression so you can easily +store tens of thousands of snapshots without using too much disk space. ------------------------------------------------- +You can create a Git repository for any folder in your computer by +running the command `git init`. -If you need to make any further adjustments, do so now, and then add any -newly modified content to the index. Finally, commit your changes with: +Run `git init` in the folder you just created, like this: ------------------------------------------------ -$ git commit +$ git init ------------------------------------------------ -This will again prompt you for a message describing the change, and then -record a new version of the project. - -Alternatively, instead of running `git add` beforehand, you can use +Git will reply: ------------------------------------------------ -$ git commit -a +Initialized empty Git repository in .git/ ------------------------------------------------ -which will automatically notice any modified (but not new) files, add -them to the index, and commit, all in one step. +You might notice a new hidden folder was created, named `.git`. +You don't need to use this folder directly in any way, but it's where +your commits will be stored. -A note on commit messages: Though not required, it's a good idea to -begin the commit message with a single short (no more than 50 -characters) line summarizing the change, followed by a blank line and -then a more thorough description. The text up to the first blank line in -a commit message is treated as the commit title, and that title is used -throughout Git. For example, linkgit:git-format-patch[1] turns a -commit into email, and it uses the title on the Subject line and the -rest of the commit in the body. +Step 5: Make your first commit +------------------------------ -Git tracks content not files ----------------------------- +Next, we're going to take a snapshot of all the files in the directory +and tell Git to store them. Git calls these snapshots "commits". +Making a commit in Git is a two step process: first you need to run `git +add` and then `git commit`. -Many revision control systems provide an `add` command that tells the -system to start tracking changes to a new file. Git's `add` command -does something simpler and more powerful: `git add` is used both for new -and newly modified files, and in both cases it takes a snapshot of the -given files and stages that content in the index, ready for inclusion in -the next commit. +The reason it's a two step process is that sometimes you might not +actually want Git to store a commit with _all_ the files in a folder. +For example, if you're compiling your program to a binary, you might +want Git to put the program's source code in your commit but not +compiled binary. You can also use a `.gitignore` file to help with this. -Viewing project history ------------------------ +For now, we're going to store a commit with every file in your folder, +as well as in every subfolder. -At any point you can view the history of your changes using +The first step of making a commit is to tell Git which files you +want to include in the commit using `git add`. To tell Git +"include all files", run this command: ------------------------------------------------ -$ git log +$ git add . ------------------------------------------------ -If you also want to see complete diffs at each step, use +To check if it succeeded, you can run `git status`. +The output should look like this: + ------------------------------------------------ -$ git log -p +$ git status +On branch main + +No commits yet + +Changes to be committed: + (use "git rm --cached ..." to unstage) + new file: README.md ------------------------------------------------ -Often the overview of the change is useful to get a feel of -each step +Next you can create the commit using the `git commit` command, like +this: ------------------------------------------------ -$ git log --stat --summary +$ git commit -m "Initial commit" ------------------------------------------------ -Managing branches ------------------ +The `-m` flag stands for "message", and it lets you set a reminder +for your future self of what you were doing. The message +("Initial commit" in this example) can say anything you want. -A single Git repository can maintain multiple branches of -development. To create a new branch named `experimental`, use +The output should look like this: ------------------------------------------------ -$ git branch experimental +[main (root-commit) 4a7e367] Initial commit + 1 file changed, 2 insertions(+) + create mode 100644 README.md ------------------------------------------------ -If you now run +You've now stored the first version of your project in Git! ------------------------------------------------- -$ git branch ------------------------------------------------- +Step 6: Make a change +--------------------- + +Now, let's learn how to make a change to a file and review the change you made. +In this example, we'll update the file `README.md`, but you can edit a +different file. -you'll get a list of all existing branches: +First open `README.md` in your favourite text editor, make a tiny or +silly change, and save it. In our example, we'll edit the first line to +add more exclamation marks: ------------------------------------------------ - experimental -* master +We're doing a Git tutorial!!!! ------------------------------------------------ -The `experimental` branch is the one you just created, and the -`master` branch is a default branch that was created for you -automatically. The asterisk marks the branch you are currently on; -type + +Next, in the terminal, run the command `git status` to get a summary of +what you changed since the last Git commit. ------------------------------------------------ -$ git switch experimental +$ git status ------------------------------------------------ -to switch to the `experimental` branch. Now edit a file, commit the -change, and switch back to the `master` branch: +The output will look something like this: ------------------------------------------------ -(edit file) -$ git commit -a -$ git switch master +On branch main + +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: README.md ------------------------------------------------ -Check that the change you made is no longer visible, since it was -made on the `experimental` branch and you're back on the `master` branch. +This output says that we've changed `README.md` since the last time +we committed. -You can make a different change on the `master` branch: +Next, if you want to see the details of how you've changed `README.md`, +you can run `git diff`. ------------------------------------------------ -(edit file) -$ git commit -a +$ git diff ------------------------------------------------ -at this point the two branches have diverged, with different changes -made in each. To merge the changes made in `experimental` into `master`, run +The output will look something like this: ------------------------------------------------ -$ git merge experimental +diff --git a/README.md b/README.md +index ffa8b85..a49e4b0 100644 +--- a/README.md ++++ b/README.md +@@ -1,2 +1,2 @@ +-We're doing a Git tutorial! ++We're doing a Git tutorial!!!! + We need 2 lines in this file so here's a second one ------------------------------------------------ -If the changes don't conflict, you're done. If there are conflicts, -markers will be left in the problematic files showing the conflict; +This output says that we deleted one line (`We're doing a Git +tutorial!`) and added one line (`We're doing a Git tutorial!!!!`). By +default Git will show the lines you removed in red, and the lines you +added in green. Removed lines start with a minus `-` and added lines +start with a plus `+`. ------------------------------------------------- -$ git diff ------------------------------------------------- +Step 7a: Make a second commit +----------------------------- + +Now that we've changed `README.md`, let's make another commit. +We're going to follow the same steps as before when we made our first +commit. -will show this. Once you've edited the files to resolve the -conflicts, +First, tell Git that we want to include the new version of `README.md` +in the next commit: ------------------------------------------------ -$ git commit -a +$ git add README.md ------------------------------------------------ -will commit the result of the merge. Finally, +and then run `git commit`, like this: ------------------------------------------------ -$ gitk +$ git commit -m "Update README" ------------------------------------------------ -will show a nice graphical representation of the resulting history. - -At this point you could delete the `experimental` branch with +The output should look like this: ------------------------------------------------ -$ git branch -d experimental +[main 32e0171] Update README + 1 file changed, 1 insertion(+), 1 deletion(-) ------------------------------------------------ -This command ensures that the changes in the `experimental` branch are -already in the current branch. +This says that the new commit is the same as the previous commit, +except that we changed 1 line of 1 file. -If you develop on a branch `crazy-idea`, then regret it, you can always -delete the branch with +Step 7b: Make a second commit (the short way) +--------------------------------------------- -------------------------------------- -$ git branch -D crazy-idea -------------------------------------- +Instead of running the two commands in Step 7a above, you +could also run this command as a shortcut. It will: -Branches are cheap and easy, so this is a good way to try something -out. +1. Get a list of every file in the most recent commit +2. Commit the current version of all of those files -Using Git for collaboration ---------------------------- +------------------------------------------------ +$ git commit -am "Update README" +------------------------------------------------ -Suppose that Alice has started a new project with a Git repository in -`/home/alice/project`, and that Bob, who has a home directory on the -same machine, wants to contribute. +The `-a` stands for "all". -Bob begins with: +Understanding `git status` output: "untracked files" +---------------------------------------------------- ------------------------------------------------- -bob$ git clone /home/alice/project myrepo ------------------------------------------------- +Now let's talk about a term you'll see in the `git status` output: +"untracked files". -This creates a new directory `myrepo` containing a clone of Alice's -repository. The clone is on an equal footing with the original -project, possessing its own copy of the original project's history. +First create a new file called `example.txt`. It can be empty. -Bob then makes some changes and commits them: +Then run the command `git status`. You should see this output: ------------------------------------------------- -(edit files) -bob$ git commit -a -(repeat as necessary) ------------------------------------------------- +---------- +On branch main -When he's ready, he tells Alice to pull changes from the repository -at `/home/bob/myrepo`. She does this with: +Untracked files: + (use "git add ..." to include in what will be committed) + example.txt ------------------------------------------------- -alice$ cd /home/alice/project -alice$ git pull /home/bob/myrepo master ------------------------------------------------- +nothing added to commit but untracked files present (use "git add" to track) +---------- -This merges the changes from Bob's `master` branch into Alice's -current branch. If Alice has made her own changes in the meantime, -then she may need to manually fix any conflicts. +This has a list of "untracked files". An untracked file is a file which +was not part of the latest commit. By default Git will ignore these +files. -The `pull` command thus performs two operations: it fetches changes -from a remote branch, then merges them into the current branch. +If you want to commit an untracked file, you can add it like this: -Note that in general, Alice would want her local changes committed before -initiating this `pull`. If Bob's work conflicts with what Alice did since -their histories forked, Alice will use her working tree and the index to -resolve conflicts, and existing local changes will interfere with the -conflict resolution process (Git will still perform the fetch but will -refuse to merge -- Alice will have to get rid of her local changes in -some way and pull again when this happens). +---------- +$ git add example.txt +---------- -Alice can peek at what Bob did without merging first, using the `fetch` -command; this allows Alice to inspect what Bob did, using a special -symbol `FETCH_HEAD`, in order to determine if he has anything worth -pulling, like this: +Then you can run `git commit` to commit it. ------------------------------------------------- -alice$ git fetch /home/bob/myrepo master -alice$ git log -p HEAD..FETCH_HEAD ------------------------------------------------- +Step 8: Make a change and throw it away +--------------------------------------- -This operation is safe even if Alice has uncommitted local changes. -The range notation `HEAD..FETCH_HEAD` means "show everything that is reachable -from the `FETCH_HEAD` but exclude anything that is reachable from `HEAD`". -Alice already knows everything that leads to her current state (`HEAD`), -and reviews what Bob has in his state (`FETCH_HEAD`) that she has not -seen with this command. +One of the most useful things about Git is that it lets you safely +experiment: you never need to be scared to change your code because you +can always go back to the old version. -If Alice wants to visualize what Bob did since their histories forked -she can issue the following command: +Before starting to experiment, run `git status` to check the current +state of your Git repository: ------------------------------------------------ -$ gitk HEAD..FETCH_HEAD +$ git status +On branch main + +nothing to commit, working tree clean ------------------------------------------------ -This uses the same two-dot range notation we saw earlier with `git log`. +This "working tree clean" message means that there haven't been any +changes since your last commit. -Alice may want to view what both of them did since they forked. -She can use three-dot form instead of the two-dot form: +Now make a change to your code, and run `git status` again. Like last +time, you should see a message like this: ------------------------------------------------ -$ gitk HEAD...FETCH_HEAD ------------------------------------------------- - -This means "show everything that is reachable from either one, but -exclude anything that is reachable from both of them". +$ git status +On branch main -Please note that these range notations can be used with both `gitk` -and `git log`. +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: README.md +------------------------------------------------ -After inspecting what Bob did, if there is nothing urgent, Alice may -decide to continue working without pulling from Bob. If Bob's history -does have something Alice would immediately need, Alice may choose to -stash her work-in-progress first, do a `pull`, and then finally unstash -her work-in-progress on top of the resulting history. +This tells us that `README.md` has been changed since the last commit. +But we don't actually want this change, so let's undo it! We can restore +`README.md` back to how it was at the most recent commit using the `git +restore` command. -When you are working in a small closely knit group, it is not -unusual to interact with the same repository over and over -again. By defining 'remote' repository shorthand, you can make -it easier: +**WARNING**: `git restore` can't be reversed! Any time you run it it's +important to be absolutely sure that you're okay with throwing away your +changes since the last commit. ------------------------------------------------ -alice$ git remote add bob /home/bob/myrepo +$ git restore README.md ------------------------------------------------ -With this, Alice can perform the first part of the `pull` operation -alone using the `git fetch` command without merging them with her own -branch, using: +Now open `README.md` again. You should see that your changes have been undone. -------------------------------------- -alice$ git fetch bob -------------------------------------- +You can stop here! +------------------ -Unlike the longhand form, when Alice fetches from Bob using a -remote repository shorthand set up with `git remote`, what was -fetched is stored in a remote-tracking branch, in this case -`bob/master`. So after this: +The commands we've learned so far (`git init`, `git add`, `git commit`, +`git diff`, `git status`, and `git restore`) are enough to get a lot out +of Git on their own. -------------------------------------- -alice$ git log -p master..bob/master -------------------------------------- +With these commands, you can keep copies of past versions of your code +on your computer and safely experiment with big changes to your code. -shows a list of all the changes that Bob made since he branched from -Alice's `master` branch. +When using Git this way, all of your code just lives on your computer. +But if you want to put your code on the Internet so that other people +can use it or back it up, then you'll need to learn about one more +command: `git push`. -After examining those changes, Alice -could merge the changes into her `master` branch: +The rest of this tutorial is about how to upload your code to a Git +repository on the Internet. The high level process is: -------------------------------------- -alice$ git merge bob/master -------------------------------------- +1. Create an account on the Git host +2. Configure Git so that it can login to the Git host to make changes +3. Run `git push origin main` to upload your code -This `merge` can also be done by 'pulling from her own remote-tracking -branch', like this: +Navigating the Git host's UI can be tricky, and it's hard for us to +give you exact directions because the UIs change a lot. +There's a rich tradition of people learning Git from their "Git friend" +who already knows Git, and if you have one of those it might be useful +to ask them if you get stuck. There are many ways to do things in Git, +so they might suggest a slightly different way. +There's also a troubleshooting guide at the end with the most common +issues folks have run into while doing this tutorial. -------------------------------------- -alice$ git pull . remotes/bob/master -------------------------------------- +Step 9: Create an account on a Git host +--------------------------------------- -Note that git pull always merges into the current branch, -regardless of what else is given on the command line. +To put your code on the Internet, you need it to be hosted somewhere. +The easiest way to do this is to sign up with a Git host. There's a list +of Git hosts (many of them offer free accounts) at +https://git-scm.com/tools/hosting. GitHub and GitLab are two popular hosts. -Later, Bob can update his repo with Alice's latest changes using +If you're comfortable running a server, there are other ways to host +a Git repository on the internet, like connecting through SSH or open +source Git forge software to your server. -------------------------------------- -bob$ git pull +Step 10: Create an SSH key (if needed) ------------------------------------- -Note that he doesn't need to give the path to Alice's repository; -when Bob cloned Alice's repository, Git stored the location of her -repository in the repository configuration, and that location is -used for pulls: +For Git to upload changes to another Git repository, it needs a way to +login to that repository. One of the most popular ways to do this is +with an SSH key. -------------------------------------- -bob$ git config --get remote.origin.url -/home/alice/project -------------------------------------- +If you don't already have an SSH key, you'll need to create one. On Mac +or Linux, you can check if you already have an SSH key by running: -(The complete configuration created by `git clone` is visible using -`git config list`, and the linkgit:git-config[1] man page -explains the meaning of each option.) +------------------------------------------- +$ ls ~/.ssh/*.pub +------------------------------------------- -Git also keeps a pristine copy of Alice's `master` branch under the -name `origin/master`: +If you don't already have an SSH key, run: -------------------------------------- -bob$ git branch -r - origin/master -------------------------------------- +------------------------------------------- +$ ssh-keygen +------------------------------------------- -If Bob later decides to work from a different host, he can still -perform clones and pulls using the ssh protocol: +`ssh-keygen` will ask you for some details. +The easiest way to do this is to just press Enter at every prompt until +it's done. -------------------------------------- -bob$ git clone alice.org:/home/alice/project myrepo -------------------------------------- +NOTE: All of the advice about how to use SSH in this tutorial is aimed +at getting it to work as quickly as possible. Setting up SSH in a secure +way is very far outside the scope of this tutorial. If you have a +security team in your organization, they might have very different +opinions about the appropriate way to configure authentication with Git. -Alternatively, Git has a native protocol, or can use http; -see linkgit:git-pull[1] for details. +Step 11: Tell the Git host your SSH public key +---------------------------------------------- -Git can also be used in a CVS-like mode, with a central repository -that various users push changes to; see linkgit:git-push[1] and -linkgit:gitcvs-migration[7]. +First, find your SSH key like this (on Mac or Linux): -Exploring history ------------------ +------------------------------------------- +$ ls ~/.ssh/*.pub +------------------------------------------- -Git history is represented as a series of interrelated commits. We -have already seen that the `git log` command can list those commits. -Note that first line of each `git log` entry also gives a name for the -commit: +That will output something like -------------------------------------- -$ git log -commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7 -Author: Junio C Hamano -Date: Tue May 16 17:18:22 2006 -0700 +------------------------------------------- +/home/alice/.ssh/id_ed25519.pub +------------------------------------------- - merge-base: Clarify the comments on post processing. -------------------------------------- +Copy the contents of that file to your clipboard. It's important that +the filename ends in `.pub` ("pub" stands for "public"). -We can give this name to `git show` to see the details about this -commit. +Then login to your account on the Git host you chose and paste the SSH +key into the appropriate place. Depending on the Git host, it's likely +under "SSH keys" in your settings. If it asks you what type of SSH key, +look for something like "Authentication Key". -------------------------------------- -$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7 -------------------------------------- +Once you've done this, you're done! Git will automatically use your SSH +key to try to connect. -But there are other ways to refer to commits. You can use any initial -part of the name that is long enough to uniquely identify the commit: +[[step_12]] +Step 12: Create an empty Git repository on the Git host +------------------------------------------------------- -------------------------------------- -$ git show c82a22c39c # the first few characters of the name are - # usually enough -$ git show HEAD # the tip of the current branch -$ git show experimental # the tip of the "experimental" branch -------------------------------------- +Go to the Git host's website and create a new Git repository. If there's +an option to "create a README.md", "add a license", or something +similar, make sure to say no to all of them. -Every commit usually has one "parent" commit -which points to the previous state of the project: +**WARNING**: If you create a public repository and push your repository +to it, then your name and email address, as well as the contents of +any files you committed and every previous version of those files, will +be on the public internet. Some Git hosts have the option to create +a private repository instead, to keep your information private. -------------------------------------- -$ git show HEAD^ # to see the parent of HEAD -$ git show HEAD^^ # to see the grandparent of HEAD -$ git show HEAD~4 # to see the great-great grandparent of HEAD -------------------------------------- +Step 13: Find the address of the repository +------------------------------------------- -Note that merge commits may have more than one parent: +Now, find the address of the repository on your Git host. It should look +something like this: -------------------------------------- -$ git show HEAD^1 # show the first parent of HEAD (same as HEAD^) -$ git show HEAD^2 # show the second parent of HEAD -------------------------------------- +------------------------------------------- +git@git.example.com:username/repo.git +------------------------------------------- -You can also give commits names of your own; after running +(where `example.com`, `username` and `repo` will be replaced with the +actual values). -------------------------------------- -$ git tag v2.5 1b2e1d63ff -------------------------------------- +If you can only find an address starting with `https://`, then +you can often translate it to the SSH format by replacing `https://` +with `git@` and replacing the `/` after the domain name with an `:`. +Here's how: -you can refer to `1b2e1d63ff` by the name `v2.5`. If you intend to -share this name with other people (for example, to identify a release -version), you should create a "tag" object, and perhaps sign it; see -linkgit:git-tag[1] for details. +------------------------------------------- +https://git.example.com/username/repo +^^^^^^^^ ^ +replace with "git@" replace with ":" +------------------------------------------- -Any Git command that needs to know a commit can take any of these -names. For example: +[[step_14]] +Step 14: push your changes +-------------------------- -------------------------------------- -$ git diff v2.5 HEAD # compare the current HEAD to v2.5 -$ git branch stable v2.5 # start a new branch named "stable" based - # at v2.5 -$ git reset --hard HEAD^ # reset your current branch and working - # directory to its state at HEAD^ -------------------------------------- +Finally, we're ready to send the information in your local Git repository +to the one on the internet! -Be careful with that last command: in addition to losing any changes -in the working directory, it will also remove all later commits from -this branch. If this branch is the only branch containing those -commits, they will be lost. Also, don't use `git reset` on a -publicly-visible branch that other developers pull from, as it will -force needless merges on other developers to clean up the history. -If you need to undo changes that you have pushed, use `git revert` -instead. +First, tell Git about the other repository by running `git remote add` +in your terminal +(replace `git@example.com:username/repo.git` with the actual address): -The `git grep` command can search for strings in any version of your -project, so +------------------------------------------- +$ git remote add origin git@example.com:username/repo.git +------------------------------------------- -------------------------------------- -$ git grep "hello" v2.5 -------------------------------------- +This tells Git to save the URL `git@example.com:username/repo.git` in +your Git repository's configuration under the name `origin`, so that you +can use it later. If you make a mistake while doing this, you can run +`git remote remove origin` and try again. -searches for all occurrences of "hello" in `v2.5`. +Then tell Git to send the information, with `git push` +(if this doesn't work, read the "Troubleshooting `git push`" section for advice!): -If you leave out the commit name, `git grep` will search any of the -files it manages in your current directory. So - -------------------------------------- -$ git grep "hello" -------------------------------------- +------------------------------------------- +$ git push --set-upstream origin main +------------------------------------------- -is a quick way to search just the files that are tracked by Git. +Let's break down this `git push` command: -Many Git commands also take sets of commits, which can be specified -in a number of ways. Here are some examples with `git log`: +* `origin` refers to the Git repository that we just added with + `git remote add` (`git@example.com:username/repo.git`). + You can use any name (not just `origin`), but using `origin` often + makes things easier because it's the default for `git push` and `git pull`. +* `main` is the name of your current Git branch. + We haven't covered branches yet, but `main` is the default branch name. +* `--set-upstream` tells Git to make this the default for `git push` for + the `main` branch. After you set the upstream, `git status` will + also tell you if you have commits that haven't been pushed. -------------------------------------- -$ git log v2.5..v2.6 # commits between v2.5 and v2.6 -$ git log v2.5.. # commits since v2.5 -$ git log --since="2 weeks ago" # commits from the last 2 weeks -$ git log v2.5.. Makefile # commits since v2.5 which modify - # Makefile -------------------------------------- +The output should look like this: -You can also give `git log` a "range" of commits where the first is not -necessarily an ancestor of the second; for example, if the tips of -the branches `stable` and `master` diverged from a common -commit some time ago, then +------------------------------------------- +Enumerating objects: 7, done. +Counting objects: 100% (7/7), done. +Delta compression using up to 8 threads +Compressing objects: 100% (6/6), done. +Writing objects: 100% (7/7), 662 bytes | 662.00 KiB/s, done. +Total 7 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) +To example.com:username/repo + * [new branch] main -> main +branch 'main' set up to track 'origin/main'. +------------------------------------------- -------------------------------------- -$ git log stable..master -------------------------------------- +Any time you want to set up a new repository, you can repeat steps +12-14, with one exception: you only need to pass `--set-upstream` the first time +you push. Afterwards you can just run the command: -will list commits made in the `master` branch but not in the -stable branch, while +------- +$ git push origin main +------- -------------------------------------- -$ git log master..stable -------------------------------------- +Troubleshooting `git push` +-------------------------- + +There are 3 main errors you might run into when running `git push origin main`. +Getting errors when running `git push` is actually a big part of using +Git, so congratulations! If you get to this part of the tutorial, you +get a little bonus experience in debugging. -will show the list of commits made on the stable branch but not -the `master` branch. +Here's a guide to why they're happening and how to fix them. + +**Problem 1: You pushed to `main`, but your branch actually isn't called `main`** -The `git log` command has a weakness: it must present commits in a -list. When the history has lines of development that diverged and -then merged back together, the order in which `git log` presents -those commits is meaningless. +Here's the error: -Most projects with multiple contributors (such as the Linux kernel, -or Git itself) have frequent merges, and `gitk` does a better job of -visualizing their history. For example, +------- +$ git push origin main +error: src refspec main does not match any +------- + +This might happen if you didn't set `init.defaultBranch` to `main` in +<>. + +If you want to check the name of your current branch, you can run `git +status`. For example, in this output, the current branch is "master". -------------------------------------- -$ gitk --since="2 weeks ago" drivers/ -------------------------------------- +------------------------------------------- +$ git status +On branch master -allows you to browse any commits from the last 2 weeks of commits -that modified files under the `drivers` directory. (Note: you can -adjust gitk's fonts by holding down the control key while pressing -"-" or "+".) +... +------------------------------------------- -Finally, most commands that take filenames will optionally allow you -to precede any filename by a commit, to specify a particular version -of the file: +To push your branch, you have a few options: -------------------------------------- -$ git diff v2.5:Makefile HEAD:Makefile.in -------------------------------------- +* rename your branch to `main`, by running `git branch -m main` + and then run `git push origin main` +* run `git push origin master` + (where `master` is the name of your actual current branch) -You can also use `git show` to see any such file: +**Problem 2: SSH error** -------------------------------------- -$ git show v2.5:Makefile -------------------------------------- +Here's the error: -Next Steps ----------- +----- +$ git push origin main +The authenticity of host 'github.com (140.82.116.3)' can't be established. +ED25519 key fingerprint is: SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU +This key is not known by any other names. +Are you sure you want to continue connecting (yes/no/[fingerprint])? +----- -This tutorial should be enough to perform basic distributed revision -control for your projects. However, to fully understand the depth -and power of Git you need to understand two simple ideas on which it -is based: +Git uses SSH to connect during `git push`, and this message happens when +SSH connects to a new site that you haven't connected to before. - * The object database is the rather elegant system used to - store the history of your project--files, directories, and - commits. +The easiest way to handle this is to type "yes" and press Enter. - * The index file is a cache of the state of a directory tree, - used to create commits, check out working directories, and - hold the various trees involved in a merge. +**Problem 3: the repository already has commits in it** -Part two of this tutorial explains the object -database, the index file, and a few other odds and ends that you'll -need to make the most of Git. You can find it at linkgit:gittutorial-2[7]. +Here's the error: -If you don't want to continue with that right away, a few other -digressions that may be interesting at this point are: +--------------------- +$ git push origin main +! [rejected] main -> main (fetch first) +error: failed to push some refs to 'example.com:username/repo.git' +hint: Updates were rejected because the remote contains work that you do not +hint: have locally. +--------------------- - * linkgit:git-format-patch[1], linkgit:git-am[1]: These convert - series of git commits into emailed patches, and vice versa, - useful for projects such as the Linux kernel which rely heavily - on emailed patches. +If you see an error like this, it means that when you created the +repository on your Git host, it added a commit to try to help you out. +That's the "work that you do not have locally" in the error message. - * linkgit:git-bisect[1]: When there is a regression in your - project, one way to track down the bug is by searching through - the history to find the exact commit that's to blame. `git bisect` - can help you perform a binary search for that commit. It is - smart enough to perform a close-to-optimal search even in the - case of complex non-linear history with lots of merged branches. +You should be able to fix this by redoing <>. +Then <> should work. - * linkgit:gitworkflows[7]: Gives an overview of recommended - workflows. +MORE USEFUL GIT COMMANDS +------------------------ - * linkgit:giteveryday[7]: Everyday Git with 20 Commands Or So. +We're not going to cover collaboration at all in this tutorial, but here are a +few more commands that might be useful when using Git on your own: - * linkgit:gitcvs-migration[7]: Git for CVS users. +* To download a Git repository to use on your computer you can run + `git clone https://example.com/some/repo` (linkgit:git-clone[1]). +* To tell Git to "un-add" a file that you added by accident, run + `git rm --cached FILENAME` (linkgit:git-rm[1]) +* To get a list of past commits, run `git log` (linkgit:git-log[1]) +* Every commit has an ID that looks something like this: + `497588f53141b531a59ed888c7d2d9b8f8a6742d`. + If you see a commit with `git log` that you want more details about, + you can run `git show COMMIT_ID` to see what changes that made since + the previous commit (linkgit:git-show[1]) SEE ALSO -------- -linkgit:gittutorial-2[7], -linkgit:gitcvs-migration[7], -linkgit:gitcore-tutorial[7], -linkgit:gitglossary[7], linkgit:git-help[1], -linkgit:gitworkflows[7], -linkgit:giteveryday[7], -link:user-manual.html[The Git User's Manual] GIT ---