#+TITLE: Magit Tutorial #+AUTHOR: Christopher Baines #+EMAIL: mail@cbaines.net This tutorial is designed as a practical introduction to Magit, both core features like committing, pushing and pulling, as well as more complicated operations like splitting commits. Problem reports, fixes and patches are all welcome. Send them to [[mailto:mail@cbaines.net][mail@cbaines.net]]. * Getting started ** Install Magit There are different ways of installing Magit, if there is one suited to your platform then try that first. Otherwise, follow the instructions in the [[https://magit.vc/manual/magit/Installing-from-an-Elpa-Archive.html#Installing-from-an-Elpa-Archive][Magit manual to install from the Elpa archive]]. ** Bind =C-x g= to =magit-status= As described in the [[https://magit.vc/manual/magit.html#Getting-Started][Getting started]] guide in the Magit manual, this keybinding can be useful. Add the following to your =.emacs= file. #+BEGIN_EXAMPLE (global-set-key (kbd "C-x g") 'magit-status) #+END_EXAMPLE ** Clone this repository Use the following command to clone the repository for the tutorial. Change =~/magit-tutorial= to the directory you wish to use if that is different. #+BEGIN_EXAMPLE M-x magit-clone RET https://git.cbaines.net/magit-tutorial ~/magit-tutorial RET #+END_EXAMPLE ** Open the tutorial, and continue from Emacs Now you have the tutorial on your computer, open it in Emacs and continue. #+BEGIN_EXAMPLE C-x C-f ~/magit-tutorial/README.org RET #+END_EXAMPLE This file and the repository itself are used for the tutorial. * Status Opening the status window is the main way to interact with Magit. This can be done by running =M-x magit-status= or =M-x g= if you have setup that binding. * Comitting Add some text in to the empty example block below. #+BEGIN_EXAMPLE #+END_EXAMPLE Use =M-x g= to open the Magit status window. If you haven't saved this file, you'll be prompted to save it, answer =y= to save the file. Once in the status window, stage the changes by pressing =s= when you have the file highlighted (the cursor should be on the line which says =modified README.org=. Once you've staged the file, it's time to commit it. First, remember these commands to use after you've written the commit message, use =C-c C-c= to finish the commit and if you wish to cancel, use =C-c C-k=. When you commit with Magit, a new window will be opened to enter the commit message. Press =c= and then =c= again to commit, which will open a window to prompt for the commit message. Use the =C-c C-c= command mentioned above to confirm the message once you've written it, and finish the commit. * Viewing the log From the Magit status window, you can view a log of commits by pressing =l= and then =l= again. You can move up and down the log by pressing =p= and =n= respectively. To view the details for an individual commit, press =RET= (also known as Enter). To close the window, press =q=. * Adding remotes A remote can be added by pressing =M= from the Magit status window. ** Creating a new (temporary) Git repository For the purposes of the tutorial, create a temporary Git repository on your computer to use as a remote. The =magit-init= command can be used to create a new Git repository. In this case, press =M-x magit-init=, and then enter an appropriate path. Remember where you've created the temporary repository. ** Adding the test remote To use the temporary Git repository as a remote, from the Magit status window, press =M= to bring up the Remote options, then =a= for adding a new remote. Enter =test= as the remote name, and then the full filename for the temporary Git repository you created above as the remote URL. When prompted to set this remote as the pushDefault, answer =n= for no. ** Easily viewing remotes and branches From the Magit status window, press =y= to get an overview of your local branches, and those on all of the remotes. Press =q= to return to the Magit status window. * Using Branches ** Creating a new branch To create a new branch, from the Magit status window, press =b= and then =c=, then select the starting point, in this case, use the default =master=, so just press =RET=. After that enter =test-branch= as the branch name and press =RET= once more. Your now working on the =test-branch= branch. At the top of the Magit status window, you should see the branch name displayed. ** Switching branches To switch branch press =b= and then =b= again. In this case, switch back to the =master= branch, so just press =RET= when prompted for the branch to switch to. * Pushing [[info:magit#Pushing][(documentation)]] For experimenting with pushing, switch back to the =test-branch= branch ([[*Switching branches][notes]]). ** Explicit pushing To push, from the Magit status window press =P=. For the purposes of this tutorial, lets push the master branch of the local repository to a branch called =test-branch= in the =test= remote. To do this, after pressing =P=, select =e= for elsewhere, then enter =test/test-branch= and press =RET=. ** Setting the upstream branch Explicit pushing is useful, but usually you'll be pushing to a single main remote. When doing this, it can be useful to set the "upstream" branch, and have Git remember this. Press =P= to begin pushing as before, then =u= to select the =@{upstream}= option. When prompted for the branch, select =test/test-branch=. Then, put some text in the following example block, and commit the change ([[*Comitting][notes]]). #+BEGIN_EXAMPLE #+END_EXAMPLE Once you're done committing, return to the Magit status window, it should say you're ahead of the upstream branch by one commit. Press =P= and then =u= as before to push this new commit. As Git has remembered the upstream branch, you won't need to select it manually. * Resetting ** Soft reset There are multiple different types of reset actions, one is a soft reset, this is the default in Magit. Press =x= then type =HEAD^= to discard the commit created in the previous section. Note that a soft reset retains the actual changes within the commit. ** Hard reset A hard reset will discard both the changes, and the commit. Press =X= to get the list of reset options, then =h= to select a hard reset. Enter =test/test-branch= when prompted where to reset to. This action will have undone the previous reset. Perform another hard reset, this time to =HEAD^= like the soft reset, to get the repository ready for [[*Pulling][Pulling]]. * Pulling At this point, the local =test-branch= should be one commit behind the remote =test-branch=. Pulling will fetch and merge that commit in to the local branch. Press =F=, the =u= to pull from the upstream branch ([[*Setting the upstream branch][as defined previously]]). Like pushing, the are a few options for pulling, but for now this is the only one needed. * Interactive rebasing Interactive rebasing is very powerful, but can be quite tricky. Magit can help with setting up an interactive rebase as well as providing context and information while it's underway. ** Preparation Enter some text in the following two example sections. Commit the change to the first section in one commit, and then the second section in a second commit. #+BEGIN_EXAMPLE #+END_EXAMPLE #+BEGIN_EXAMPLE #+END_EXAMPLE The interactive rebase we'll try will reverse the order of these commits. ** Starting the interactive rebase From the Magit status window, press =r= then =i= to select the starting point for the interactive rebase. Move down (using =C-n=) to the first of the commits you just created, and press =C-c C-c= to start the interactive rebase. This will open a buffer for inputting the operations, you should see the supported operations at the bottom of the buffer. In this case, use the =M-n= and =M-p= to reverse the order of the commits. Press =C-c C-c= to finish the interactive rebase. * Splitting commits To split a commit, you can combine Magit's ability to revert portions of a commit with an interactive rebase. ** Preparation First, lets create a single commit to split. Add some text to both of the following example blocks. #+BEGIN_EXAMPLE #+END_EXAMPLE #+BEGIN_EXAMPLE #+END_EXAMPLE Then commit the additions as a single commit. ** Starting the interactive rebase As the commit needing splitting is the most recent, it's not necessary to rebase to edit the right commit, however, in general, you may need to interactively rebase, and choose to edit the commit you intend to split. In the Magit status window, begin the interactive rebase, and then edit the most recent commit. Once you've begun the rebase, in the status window, select the commit to split and press =RET= (Enter) to show the full details. ** The actual splitting To split the contents of the commit, we are going to remove some parts from it. To do that, we can revert those parts, stage that change, then revert the staged changes. Once the staged changes have been reverted, those changes can be appended to the commit, effectively removing that part of the commit. Once this is done, the extracted part of the commit can then be staged and committed. First, select the part of the commit to remove and split out. This can be a file, or a part of a file. To select individual lines, move the cursor to the start or end of the section, use =C-Space= to start selecting lines, and then =n= or =p= to move up or down. Once the target region has been selected, use =v= to begin reverting the region, press =y= to confirm. Then stage the unstaged changes, select them and press =s=. Once this is done, revert the staged changes, move the cursor to the "Staged changes" section, press =v= and then =y= to confirm. Then, amend the current commit by pressing =c= then =a=. Once this is done, stage the unstaged changes, and commit them. When you're finished committing the unstaged changes, continue the rebase to finish. ** Splitting one commit in to more than two commits If you wish to split one commit in to more than two commits, then you can repeat the above process again once finished, or revert all the parts you wish to split out, and then stage and commit the appropriate parts of those unstaged changes. * Viewing a file at a particular revision ** With =magit-find-file= Press =M-x magit-find-file= select the revision (e.g. =HEAD^^=) and press =RET= to select the default file. ** With =VC= ([[info:emacs#Old%20Revisions][docs]]) The Emacs version control interface (called VC) supports viewing a file at a specific revision, press =C-x v ~=, then enter the desired revision (e.g. HEAD^^). * Next steps From the Magit status buffer, press =?= to get the full list of commands. You can view the Magit manual within Emacs, start by pressing =C-h i= and then navigating to the Magit section. There are packages other than Magit that extend Emacs to work with Git repositories. [[https://github.com/syohex/emacs-git-gutter][git-gutter.el]] provides indications within each buffer when you add, remove or modify the contents. [[https://github.com/rmuslimov/browse-at-remote][browse-at-remote.el]] allows you to jump from Emacs to common Git hosting providers, for example, a specific commit.