LongCut logo

9 Techniques to Boost Your Git Workflow with Magit

By System Crafters

Summary

## Key takeaways - **Clone with username/repo shorthand**: Magit clone recognizes username/repository name like davidwilson/dotfiles and clones from GitHub by default, or use gl: for GitLab. It prompts for local path and sets origin remote automatically. [02:06], [02:42] - **Stage hunks or lines precisely**: In status buffer, press s on a hunk or selected lines in modified files to stage only those specific changes for commit. This enables independent commits for each improvement in dotfiles. [11:50], [12:46] - **Instant fixup for earlier commits**: Use C-f in status buffer to instantly add staged changes to any earlier commit without full rebase. Select commit from log view and confirm to update it. [23:29], [24:23] - **Spin-off commits to new branch**: Press b s in status buffer to spin-off recent commits to a new branch like config-updates and reset original branch to prior state. Requires original branch pushed to remote. [27:00], [28:17] - **Force push with -f after amends**: After amend, extend, or fixup changing history, use P -f p to force-with-lease push overriding remote branch. Avoid on shared branches to prevent issues. [35:08], [35:52] - **Stash with zz for safe pulls**: Press z z in status buffer to stash staged/unstaged changes with a message, then pull or rebase. Use z p to pop and delete stash after. [37:31], [39:10]

Topics Covered

  • Magit Clones GitHub Repos by Username
  • Stage Specific Lines for Atomic Commits
  • Instant Fixup Amends Earlier Commits
  • Spin-Off Moves Commits to New Branch
  • Force Push Overwrites Rewritten History

Full Transcript

[Music] [Music] what's up everybody welcome to system crafters i'm david wilson and today we're gonna kick off part two of our new mastering get with magit series

and in this video i'm gonna show you how you can use magic to perform your day-to-day get operations much more efficiently than what you might be able to do with the get command on the command line so instead of covering every magic feature

exhaustively i'm going to use a scenario driven approach to show you how to accomplish specific tasks that i use magic for on a day-to-day basis both whenever i'm managing my personal dot files repository and when i'm

working on larger projects where i have to collaborate with other people so since i'm not going to go into great detail on everything let me know in the comments if there's anything in particular that you would like to see covered in more depth in a

later video in the series and i'll see what i can do okay so cloning a repository so while it's not something that you might do every day you'll eventually need to clone a git repository from a remote location

typically a collaboration site like github git lab or source hut so the easiest way to do this from anywhere in emacs is to run the magic clone command and you can use meta x or alt x

to pull up the command listing to do that so i'm going to run i'm going to type in magit dash clone here and what it's going to do is prompt me for the source for cloning and it gives me three

options here if you see this here in the echo area we have a url or name path and local url for the purpose of this episode we're just going to focus on url or name because typically you're

going to have a url for the repository from github or gitlab whenever you're looking at the repository site you can basically copy the url and then paste it here to to clone it one interesting feature

though of the magic clone command is that you can type in the username repository name of a known repository or of any repository on

github and magic will extrapolate and know to clone from github by default so if i type in davidwheels davey will slash dot files it's going to continue asking

me for a location to which i want to clone this repository and that that david dot files that i'm i'm telling it the clone is actually my own personal doc files repository on github you can actually find that on

my my profile on github so i'm going to put this under projects slash code dot files and then press enter now it's going to ask me to set my remote push default to origin

you definitely want to say yes here because you want to have an origin setup automatically for pushing and pulling for changes to and from your remote remote repository on github i'll type in

my passphrase here and then uh that should finish cloning in just a little bit because it takes a little bit of time to clone a larger repository and once it's finished it should pull up the status

buffer for this repository uh using the magic status command that we've seen before in the previous episode and as you can see here uh that status buffer did show up i realized i just i forgot to

turn on my command log here let's see dw toggle command window i'm trying a new thing today where i have a little window up in the top right corner that will show you the keys that i'm pressing and the command they're bound to so let me know if you

think that's helpful okay so now we're in the status view for the repository that i just cloned down we can look at the recent commits as we saw in the last uh last episode and we see that we have all the

information here to get started so let's jump back over to the presentation um now interesting thing about the uh the magic clone command that we just saw

is that uh there's also prefixes you can use on the user slash repo name as we saw before for um either github or get lab you can use either gl or get lab

with a colon and then the username slash repo name to clone from gitlab instead of github if you want to see where these names are configured you can go to the magic clone name alist variable with control

hv and you can see there's basically a list of of items here that are basically regular expressions uh that map to a particular host name and uh the variable that you pull your username

from so if you wanted to add another one here say for sourcehut you could do that by adding another item to this list with the appropriate regular expression now maybe you don't need that functionality all the time so it might

not be super helpful but since most things you see online i'm not going to say all things obviously but since a lot of a lot of repos you see online are on github it's kind of convenient to have this ability to just

use username repo name when you're cloning something inside of emacs so let's see anything else interesting to say here yep so basically we're at the point now where we have our

repository cloned and i'm going to help myself out a little bit by manipulating that repository this is nothing that you need to do i'm just doing it for my own purposes for the demos in this video so i'll just run

this little selection of code here and uh just as a way of uh you know give you giving you some value from what you see there is a way that you can really run these magic commands as functions in

emacs list so you can automate certain things like resetting a branch to a particular commit so uh just keep that in mind you can use a lot of the magic commands as functions or even the internal functions directly in emacs

list code if you want to automate some of your git operations but that's for another whole video if you wanted to know more about that all right so looking at commit history so before we get into the more interesting and useful features of magic

let's take a look at how you can view the commit history of your git repository other magic operations like cherry picking and rebasing all use the same kind of log view so

it's pretty helpful to be familiar with it before you start using the more advanced features of magit so you can view the commits from the current branch by using the magic log current command

or you can open the status buffer and press l so what i'm going to do is jump back to that status buffer i'm going to press l and when you press l it brings up this whole big panel with a lot of options

and some commands down here for getting listings of commits inside of your repository so the l command for current is the one that i'm talking about here so if you press l inside of the status buffer it will bring up

a listing of all the commits in the current branch and since i'm currently in the master branch we're seeing commits in master and a whole listing of commits here each of the items is listed in reverse

chronological order meaning the newest commits are first and then they go down from there we see the commit hash or at least the short hash for the commit we see the commit message for the commit

we see the author and how long ago the commit was made so you can get some decently useful information by taking a look at this and you can also move use your arrow keys or any other movement keys you have bound to

move to the list and press enter on any of the items to see a diff of the the commit in question which can give you some more information about when the commit was made uh you know which branches is contained in

etc so this can be a pretty useful view if you're doing some research into the state of your repository so let's see uh if you press the q key it will close that views it's a quick way to get

out of that and i press l i'll get back into that view again and then um let's see i think that yeah it shows only a limited number of commits by default so if i press l

and i go down to the bottom of the buffer um it shows me commits back to well at least in my case it's probably done by number of commits but in my case i can see commits from 11 months ago i can also press the plus sign in this

buffer for it to load more commit history so it will load even more commits if you if you need to see more inside of this same branch another really interesting function of this view is to allow you to

search across the uh the commits that you have here so if you want to search for a commit with a specific word in the commit message or releasing the first line of the commit message you can do that

uh either using the built-in search i search commands or if you use swiper or if you use console line you can use any of the buffer searching functionality that you use in any other buffer to search this buffer

as well so i'm going to use consult line since that's what i have set up i'm going to type in kimx2 or just kima then that's enough to pull up a chemex2 listing i can also type in

a geek's colon and see anything that has geeks in the message so it's a very convenient way for you to find commits related to a specific thing in case you wanted to look for something locally without having to go to github or gitlab

and search across your repository to find a commit with a particular message so also you might want to view commits from a specific branch so maybe you want to see commits from a branch that you're not currently on for the purpose of just

looking at the commits that are there maybe you want to cherry pick some commits later something like that so you can use the lo key binding inside of the status

buffer or the magit log other command to pull up this log other buffer so i'm going to press l o here let me do that more slowly l

and then you see that o is down here so log other and it's going to ask you for the log rev colon or comma s which doesn't make a whole lot of sense but it's basically like what what branch do you want to make a

listing for or even a commit you can see the lineage lineage of a particular commit if you type in a commit hash here an easier way to do this is to just press tab to get a completion list

and then it will give you the list of uh branches that you might be interested to log so i can log this termix branch here uh by pressing enter enter and now i can see the log for that particular branch which is like a dead

branch basically on my repository but you can get the uh the log for that even though that's not a currently uh it's not a branch that i have created locally it's actually a branch on my remote

my github repo i can still look at that because all that information is still cloned locally all right so i think that's everything for logging so

it's not really something you're going to do all the time but it is useful to understand how other views in magic will will be displayed and we'll see actually

one example of that in a little bit okay so now if you've if you've been using git for a little while you're probably familiar with staging whole files to be committed with the git add command so if you're adding a new

file or maybe you're making changes to an existing file in the repository you would typically use git add to add that entire file the changes of that entire file into the staging area so they can be

added to a commit now in magic status buffer it's actually really easy to add only certain subsections of a particular changed file

to be committed so basically all you need to do is to go into your status buffer and then we can see how you can add various different granularities of these modified files to be committed

so i'll go into this buffer and i already have some changes that i put into one of the files in this repository in the emacs.org file so we can see that there are uh three hunks in this

file so a hunk is basically a section of the file that has a diff or has changes applied to it so there's one section here with a line that got removed

and there's another section with a line that got added and then there's another section with a variety of additions and removals so if you wanted to add the whole file to be committed you could just put your

cursor on the the modified emacs.org line press s and then it gets added to the stage changes section and then i can press u to unstage that thing but what if i wanted to only stage some part of this so if i

wanted to go into uh this hunk that has all the changes to my erc settings i can actually press s anywhere inside of this hunk and it will stage only that hunk or only that part of the file that

was changed and if you go down to the stage changes section you can see that only the erc settings are here similarly i can press u to unstage those to send them back to the unstaged

changes view and uh one of the more useful aspects of this is that you can select specific lines and then stage only those specific lines so if i only wanted to stage this

particular line that adds a particular configuration value i can select those using whatever keys used for selection and buffers in emacs and then press s and only that single

line will then be staged so if i close this and go down to my stage changes section you can see that the the single line that i had selected has been added here so this gives you the ability to be very very specific about

which changes are going to be included in commits and it's something that i use very very often whenever i'm making commits for my own dot files repository because usually i have multiple changes i've got sort of

sitting around in my emacs configuration that haven't been committed committed yet and whenever i go to commit those i want to make indiv independent commits for each little improvement that i make so then i go

in that file select those specific lines stage them and then make one commit out of only the things related to that particular change so this is something that you will probably use quite often for your own dot files repository you

might use it whenever you're collaborating with other people too but in my personal experience i use it quite often with the doc files let's see what did i miss here

so one other thing that is very important to note uh if you were to um find a line here like let's say this one here where i have changed this uh oops this erc prompt for nick serve

password variable to erc prompt for password um in this case this indicates that this line has been changed so it says that one line has been removed and another has been added but really this is just

one line that has been changed if you do independent or individual line staging definitely make sure that you select both of those lines both the removal and the addition to make sure that the correct diff gets

included in the commit because otherwise what's going to happen is if you only select the addition and commit that when someone pulls those changes down they're going to have two lines instead because the old line never got removed

using that diff so make sure that you include both the removal and the addition line and stage those together so you can see that i have them both here now so i'm just going to go ahead and create a commit using these

lines that i have already staged so i'm going to press c and then that brings up the the commit panel and i can press c again for create commit we've covered this in previous episodes so if you're not familiar with what we

just did you can go back to that previous episode and and look at that uh section at the end of the video so i'm going to make a commit here i'm going to type in

a message i'm going to say change some erc configuration values and since this is in my emacs config i'll just put a little emax tag in front of it

also you can add more information below this so i can say let's change the shortened value and then update our password

variable name and uh one thing i also wanted to point out here i don't know if i pointed out in the last video uh there's a nice feature of magic where if you start typing a commit message that's

too long for the conventions of commit um message length or i guess the log message length it will give you this little red outline of the text past that

point i think it's like what is it how many characters is that a 70 characters or 68 characters something like that basically um and that's pretty useful because in most uis that display git commits

um they they're meant to be shown on like an 80 character wide screen so we're trying to make sure that the length of the the commit message does not kind of have to be wrapped around or truncated so definitely good to follow

the guidance that's given here and make sure that the the first log message of your commit doesn't go longer than that uh character limit and then add extra information you want to describe your commit in the section below

you can add as many lines here as you want to it's basically wow sorry about that it's basically just uh you know arbitrary lines of text that gets shown up in the commit log whenever you look at it later

so to finally make this commit i'm going to press control c control c to confirm it and now we can see that we have our new commit uh change some erc configuration values here it also tells us that the commit

that we just made is unmerged into origin master so we basically need to push that commit to to make it live on our master branch on the remote repository but we're not going to do that just yet we're going to cover some other things

first so um let's see what's the next thing we want to talk about here so what if i uh wanted to add a a change to that commit that i forgot to

add a lot of times whenever you're making commits maybe there's like a line that you missed in the file or maybe another file that you wanted to include that you forgot to include imagine makes it really easy to extend

your most recent commit with additional changes uh that you are adding to the staging area so if i were to go back into the

the dot files um repository status pane i can go and select some more of the file here uh in fact maybe let's just no let's just select this little section here we're going to arbitrarily select some some

section here for this i'll add some more lines into it and now we can see that i have some things added here in the staging area so what we're going to do now is press c for commit but instead of pressing c

again to create a new commit what we're going to do is use the e letter to extend the previous commit and what this does is it takes the changes that are in the old commit

and the new changes that you have staged and then merges them together in that previous commit so if i press e it's going to basically create the commit immediately i don't have to to do anything else i don't have to edit the commit message

nothing it basically just creates a new commit using the original commit plus the new changes if i pull that diff up for that commit you can see that all the extra stuff that i added

is there now something to keep in mind here what i've just done has changed the commit history of this branch so that commit that existed before with that particular sha-1 hash that commit does not exist in this

branch any longer now it's a new commit that has the same log message but a different diff inside of it this comes into play later when you try to push changes to a remote

remote repository for the same branch if you've already pushed once before to that branch and you try to push again it's going to give you an error saying that those two branches don't match up and you'll have to force push that branch to actually override

what's already there i'm going to talk about this in more detail in just a second but i wanted to make that uh clear to you before we move forward that when you use this extend command or or reword or amend any of those is

basically changing the commit that you are modifying and you're going to have to force push the branch whenever you get ready to push it again now if you if you haven't pushed that branch to the remote yet you

won't have any problems because there's no history to be in conflict with so everything's fine from that perspective all right so uh what i showed you before was uh extend

however uh if you want to if you do want to actually edit the commit message like let's say you write very detailed commit messages and you wanted to also mention the thing that you forgot to include

you can use ca instead which is for amending the commit so if i were to go into these changes and let's say i'll select this section here and add it to the staging area i can

press c and then press a for a min as you can see down here in the commit panel and then it's going to ask me for the commit message and what's going to happen here is i can add something new to the commit

message and say here's the new information press control c control c to confirm the commit and then that's going to take the newly staged changes that i added to the

staging area plus that new commit message and it's going to recreate that same commit again so you can see we have the the new information in the commit if we look at it in the log

we can also see that if the new lines that i added are also there so you have two options whenever you're trying to update a commit you can either extend it which adds the stage changes that you have

into the previous commit or you can amend it which adds those stage changes and allows you to edit the commit message now if you only want to edit the commit message you can use the reword command

if you press c there's the w command here for reword if i press w then it just pulls up the commit message editor last edit and then you will be able to

edit that commit but if you haven't actually let me cancel that out i'm going to use ctrl c ctrl k to cancel that and i will um i'll add this line

to the staging area i'll add both these lines to the staging area so i have these two lines that are added now that they're staged and i'm going to use this to prove to you that if you use reword it doesn't actually take those

changes whenever you are rewording your commit so press c and then w to reword and then i can say i think the focus is going to the wrong place

uh here is the final edit control c control c wow wait a second is it going to take that in yeah okay it didn't do that thank god all right so

this in the stage changes list there still is those changes that i staged those did not get added to that commit whenever i created it however however if you go down to that commit in the status buffer press

enter you can see that the uh the final line that i added is there so those are three ways to edit a commit once you've created it however those things only work on the most recent

commit that you made they don't work on three commits ago so there's another way to do that which i'll show you right now so if you've already made newer commits and then you realize oh crap i forgot to

add a file to the second or third commit previously there is a way to uh to accomplish this on the command line you would normally use a command called git rebase to do this and it's generally considered to be a

more advanced git technique and something we'll we'll cover in the next video where i talk about more advanced get operations inside of magic however magic makes a specific operation much easier

with the instant fix up feature so you don't have to understand rebase really to be able to use this which is a great thing so if you want to add changes to an earlier commit all you need to do

is press the c capital f command inside the status buffer and that gives you the instant fix up operation so what i'm actually going to do is unstage these changes here

oh no let's let's do this first i'm going to create a commit with those two changes i just unstaged so let's let's add those i'll create a new commit i'm going to call it uh let's see

i wonder where my focus keeps jumping to so emacs um uh update um uh toc headings so i'm basically updating the table of contents headings

in this file let me use ctrl c ctrl c and now the update toc headings is the latest commit on this branch however what if i wanted to add the remaining changes for the erc

configuration stuff to that previous commit i can stage that and now i can press c and then i can press capital f for instant fix up and what this is going to do is bring up that

that uh commit log that we talked about before and show me all the commits on this current branch and ask me which one that i want to apply those changes to and it tells me in the in the header

area here um select a commit and then press control c control c to apply those changes to that commit or control c control k to abort so if you make you change your mind you don't want to actually do this fix up

press ctrl c ctrl k however in my case i want to change this uh change some erc configuration values commit to take in those missing changes that i forgot the last time

so if i press ctrl c ctrl c here it's going to change that commit we're going to see that the stage changes that i had here before are now gone because they've been added to that commit and we can go select that commit and go

look at the diff and see that that large deletion chunk here that i had is now included in that commit this is a super super helpful uh piece of functionality in magit that

i use all the time because i'm kind of a stickler for making sure that i have a good commit history so if you're working on a branch where you're doing a lot of commits sometimes you will forget things and you will need to add those

changes that you missed into an earlier commit and this is the the easiest and the fastest way to do that once you start getting used to these these magic status buffer key combinations it's really really fast

like extending a commit or using fix up on a commit is just lightning fast and it will make your git workflow a lot more efficient it's really great let's see anything else yeah so like i

talked talked about before any operation that you do in magit or with git that changes an existing commit will require you to force push that branch later if you have already pushed that branch before so

just keep that in mind and i'll show you that in a little bit how that works okay so uh creating a new branch from the changes of the current branch uh this is another thing that i use quite often because i

i uh i run into this problem myself whenever i'm doing work uh with with git repositories so if you uh if you start working on a particular branch and you start making

a lot of commits maybe you're writing a new feature or doing some big changes in your dot files repository anything like that at some point you might realize that you have been making commits to your

main branch or your master branch when you didn't intend to be making commits there you meant to be making it into a different branch because maybe you need a feature branch that you're supposed to be working in to contain all these changes thankfully

magit has a very nice command called spin out spin-off which is allows you to take those commits you've made to that branch and then move them to a new branch and then reset the

previous batch branch back to where it was before you made those commits so it makes it so that you don't have your master branch locally out of sync with what's remote and uh then you can still move

your changes over to the new branch that you need to use for like let's say creating a pull request or or anything like that so i'll show you how to do that right now so it turns out that we have been making commits to master already which is good

because what we need to do is create a spin-off branch with those commits so these two commits we have here uh for changes to our emacs configuration i'm gonna press b to pull up the branch panel down here

and we haven't really gone into detail on uh branching but i'll just quickly point out that if you press c you can create a new branch it will ask you what the base of the branch oh sorry c is for checking out a branch so maybe you want to check out a branch from the

remote repository or maybe one of the existing branches you want to create a new branch off of an existing branch also you can just create a branch within but we're going to use the s command for

spin-off when i do that it's going to say what the spin-off branch is so i'm going to give it a name i'm going to call it uh config updates when i press enter it's going to we're

going to see now that we're currently in the config updates branch and since this is a new branch it says that the origin version or the remote version this branch currently does not exist because we've never pushed it yet

and we get the listing of the recent commits now i can switch back back to the master branch to double check to make sure that it actually is back to where it was before so if i press

b i can see check excuse me i can press b again for checkout and it will ask me which branch i want to check out in this case i'm going to select master here and then we can see now that the

master branch does not have those configuration change commits that we made before it's back to the commit that it was at before i made those commits so it seems that master is now in a good state again

so if i press bb one more time i can go back to that config updates branch that we just created and we see that the two commits that we added are now there so everything's in a good shape right now we've got those commits moved over

to a new branch and we can continue working as we had been doing before i love this feature it saves me a lot of time because otherwise you have to like you know create a new branch off master and then manually go back to master and

reset that back to the previous commit you no longer have to do that if you use uh the spin-off feature of magic branch which i think is really excellent so let's see where are we at here one

thing i need to mention is that the spin-off feature actually only works if the branch you're creating the spin-off from has been pushed to the remote i think there's some tracking information that

it needs to use to determine uh where the starting point is for the commit so uh just keep in mind that uh if you have a branch you've created that has not been pushed the remote yet and you

try to spin off from that branch to another new branch the the original branch may not be changed back so just keep that in mind all right so pushing a local branch to a

remote so once you've made a few commits to a branch you'll eventually need to push those commits to a remote location like github so that you can share those changes or maybe even collaborate on those changes with other people

so imagine has a very convenient interface for this which enables you to do all the things you might need to do on the command line for pushing with just a few key presses and this is one of the places where

magic makes me way way faster than i would be on the command line which is really great so usually when you create a new branch there will not be a matching branch on the remote repository yet so you'll have

to push that new local branch to the remote to establish it there on the remote and as we saw before inside of our whoops uh as we saw before inside of our status buffer

uh it says here that the config updates branch does not yet exist on the remote so if we press the capital p key inside of the status buffer it's going to give us this push panel

and it's going to give us a few options here but the the most important one for this particular scenario is the p key which then automatically says okay for the origin remote what we're going to do is create

this config updates branch there and then push all of these commits to that branch so that it now exists on the remote repository also and i want to take a very short digra digression to tell you what a remote is

we'll cover this in more detail in the next video but a remote is basically just another it's a it's a url to a remote repository so by default when you clone a github

repository sorry cloner remote repository using git clone typically a remote called origin is going to be created and that's the original location where you cloned

that repository from now if you're on github and you fork a repository it's going to create a copy of that repository in your personal github account so if you clone the fork you also need

to be able to get access to the original commits so this is where you add a new remote like upstream to add another remote where you can pull commits from the original repository while still working in your

fork repository we'll talk about this workflow in a little bit more detail in the next video i just want to let you know what remote is since we're going to be talking about that a little bit more in this episode so i'm going to press p here to push

this branch to the remote called origin and in a few seconds it should finish that and now it will tell us here in the status buffer that uh now we have the config updates

branch with that same commit pushed remotely so this tells us basically that the status of our local branch and the remote version of that branch are the same we're at the same commit on both of those which is great

so now if you want to push new changes to the same branch you can just use that same capital p and then p again so there's no differences between the remote branch and your local

branch other than just you having some new commits to push you can just use p capital p p to push those commits and then everything should happen without any further intervention from you which makes it really fast if you want

to just pop up and pop open the status buffer and hit capital p lowercase p to then push whatever you've been working on currently so let's go back to our emacs.org buffer

did i not open that let's see let's go to emacs.org in this folder uh what i'm going to do is let's say i'll go here to this mastodon section i'm just going to delete the configuration for

for mastodon for the mastodon package i'll go back into the status buffer with my key binding then i will stage this part of the file that i changed i'll create a commit emacs oh okay yeah it's it's jumping the

wrong place emacs colon uh remove uh mastodon configuration ctrl c ctrl c to confirm and now we've created that commit

so now i can use capital p then p to push that new commit to that same uh remote repository branch and now it's it's finished and we can see that the push status also says that the same commit is

there on the remote very fast you don't have to go to the command line and type git push origin whatever you can just hit capital p p to push those new changes which is very very fast compared to what

you would do in the command line now uh here's the point where we talk about that thing i said before where if you push if you make changes to existing commits on a branch

using uh amend extend or fix up then you're gonna have to force push the new state of that branch to the remote and it's very easy to do this

in fact it's very convenient to do this as well because it's only just another little key press that you put into the whole sequence so you'll get very fast at doing this whenever you need to so let's say i want to remove this whole

mastodon section maybe i realize oh i need to remove more of that commit so uh sorry more of that configuration section in my emacs.org file so i'm going to delete this whole part here

save it open my magic status now i've got a couple of changes in this emacs.org file so i'll stage those i'll press c e to extend that commit so now i've changed this commit that i've already

pushed so there's a new version of the remove mastodon configuration commit and you can actually see here that there is a divergence in these two

uh versions of the branch the the local commits that are unpushed to origin config updates has a commit with the same log message but it says e441c which is the the shot one hash

if you look at the unpolled section it's going to tell us that the remote repositories config updates branch has a sha-1 hash of 4ac 4b34 which is different that means that there's a different

different commit there so to actually push this the remote we're going to have to force push it if i try to use capital p p right now it's actually going to give me an error saying that it can't uh resolve the difference between these two

branches so it will look like this at first fail to push some refs if you press the dollar sign key it will give you the error information it says updates were rejected because the tip of your current branch is behind its remote counterpart

which is not really accurate because what the reality is is that you have a different commit history now so to get around this issue capital p then you type dash f

for force with lease so if i type dash f it activates this force with lease option for git push and now if i push p

again if i press p again it will force push that latest state of the branch to the remote so that i overwrite what's already there so it's very important to realize that

this is overriding what is on the remote repository those commits still sort of exist but they don't exist in that branch any longer so um it can be a problem

if you're collaborating with other people on a branch like let's say if you force push to a master branch and someone else is working on that repository with you if they try to pull changes from master they're going to get some major issues

that they have to deal with to reconcile that forced push that you did because you basically overwrote the history so definitely do not use force push on a branch that you share with other people

only do it on your own branches that you've created for your development purposes just a best practice to to keep in mind there

all right so the next thing is um saving local changes for later so there's going to be times where you're going to need to move some uncommitted local changes out of the way so you can perform some other

git operation like a pull or a reed base so if you ever try to pull from a remote git repository sometimes git is going to tell you oh you can't do that because the changes that are coming from the remote repository actually conflict with the

uncommitted changes you have in your local copy of that repository so we need to move those out of the way so that we can pull them and then reapply those uncommitted changes that you had to

reconcile the differences between them so git already provides a command for this called git stash so you're basically stashing those changes away you're saving them somewhere so that you get them out of your local

repository folder so they don't show up in your git status listing any longer so in magic you can stash changes from the status buffer using

zz which is very convenient to hit so if we go back to the status buffer we can let's actually go make some changes in this file i'll just delete this media heading and go to the status

buffer so now we can see there's a couple changes in this file if i press z it brings up the stash menu and then you can see that z the second z that you would press stashes both i think it means it stashes

the um staged and unstaged changes for files that are actually a part of the repository which typically is what you want so i'm going to press z here and it's

going to ask me for a stash message so maybe i'll say before pulling and that's just a description you can use to remember why you had stashed those changes so here in the new stashes list that

appears i can see that there's one stash and it says on config updates before pulling if i press enter on that we can actually see the diff of those stash changes so it's almost like creating a commit

but it's not something that goes to the remote repository it's something that just gets created locally so that you can get back to those changes later whenever you're ready to use them so now if i wanted to get those changes

back i can press z and i can press a to apply the changes so when you do that it's going to apply those changes from that particular stash

that i had selected here with my cursor and now those are back in the unstaged changes section um so now there's another thing you can do like so you see that

when i use apply it basically kept that stash entry that i had before but a lot of times you probably don't want to keep those around because it's just going to create a lot of craft in your repository so instead you can use z

and then p for pop actually let me get my cursor out of there to show you a different way to use stashing or applying let's say if i press z and press p for pop it's going to ask

me which stash here that i want to to pop the reason why it asks me is because i don't have a cursor on a stash entry inside the status pane so now it's just just ask me which state stash i want to

use if i press enter it's going to apply the changes from within that stash and then delete that stash entry which is really useful because we don't want to have that thing sitting around forever

so that's how you can save changes that you have sitting around in your unstaged changes section or even in your stage changes section and get them out of the way in case you need to do some other git operation

all right that was all for that okay another really important thing is pulling new commits from a remote into a local branch so regardless of whether you're working on your dot files repository or collaborating with others on a project

you'll eventually need to pull commits from a remote repository so if you are in the magic status buffer you can press the f key to open up the

poll panel and it this looks very similar to the push panel because the functionality is basically just a mirror of the other so in this case we can pull into the

config updates branch from origin config updates using p so it's it's the same as with push if you hit type capital p p it pushes to the remote version of the same branch if you

type capital f and then p it will pull from the remote version of that same branch and typically you would do this for your master branch let's say you're not making any new commits your master branch you just want to pull in the

latest stuff from master you can do that with capital fp to pull those things in but you have to be on the master branch for that to work in that way so i can press p here and since there

are actually no new commits that i don't already have on that remote branch it just finishes there's no big deal so in in the happy case you don't have to deal with any merge conflicts

uh maybe just you get some new commits from that remote branch so let's see uh oh yes and i also should mention that you will need to stash your local

changes so if you have commits that are coming in and they conflict with any of the local files that you have you'll have to stash those first then pull those commits and then apply

that stash or pop that stash to reapply the things that you had before and you may end up with merge conflicts you have to deal with which we'll show in a little bit of detail in just a second all right so pulling new changes from

another branch so this is something i use more often uh because usually i'm working on a secondary branch and i need to pull in the latest changes from from the upstream so let's say i wanted

to pull in something from the master branch or the main branch you can use a capital f u which will allow you to set the upstream branch so in this case

i type capital f and if i type u it will ask me what my upstream branch should be in this case i can say i want it to be origin master however i'm not going to do that right now because we're going to end up with an issue but

the idea being that you can set the upstream as a branch you want to pull changes into your current branch so that you can use that u key every time again in the future

you can also use e instead so if i type capital f and e it basically just gives you a completion list of any branch that you could pull uh changes from and uh that can be

useful for pulling things from any branch on the remote or any of the remotes that you have configured so um a lot of times what you'll have to deal with excuse me

is a new commits to the branch the upstream branch that you're trying to pull from that um add functionality that that you need to apply your current branch's changes on

top of so in git there's sort of two ways you would do this one is through through merging so basically you merge master into your feature branch or you uh and the thing about merging is

it creates an extra commit that says how those branches were merged which is typically not very desirable whenever you're doing this kind of distributed development the other option is called rebase and

what rebase does is it takes the new commits from the branch you're pulling from and then reapplies all the commits you made to the current branch on top of those new commits

and uh basically changes the entire history of your new of your branch to have those new commits plus the things you added after those new commits so um this is a little bit more complicated

because um you're rewriting the history of the branch now and uh it doesn't match up cleanly as the commit history you had before so you will have to force push if you use this

rebase functionality but this is the approach that i use because i like to have a clean history with no merge commits where they're not necessary so the way that you can do this is to turn

on the rebase option in the pull panel so if i go back into this pull panel let me just stash these changes really quickly uh i'm going to press capital f and then you'll see

there's a configure section here with an r key and this is actually a an option that gets saved in your com your local git repository configuration so if i press r it's going to turn rebase on it's

going to set it to true and this means that any time that i pull on this branch now it's going to rebase instead of merging any new changes that come in so uh the thing that i was talking

about before using you for upstream i'm going to pick you now and then i'm going to pick origin master as my upstream and then press enter so what's going to happen is it's going to pull

those changes from origin master into my branch and then reapply the commits that i made on top of that and while it did that it found a merge conflict thankfully it's a very simple one uh but you can see that

there's a git error could not apply the specific commit hash and it will give you the listing of where it's currently at in this rebase operation we'll cover rebates in more detail in the next episode so that you understand really what's

happening here so uh for a particular commit this change some erc configuration values uh there's a conflict if i press enter to go into this file i can actually see the uh the merge markers that allow me

to make a choice about which one of these changes to to accept or how to merge them together uh we'll cover merging in more detail in the next episode as well but for now i'm just going to delete this whole section because

i didn't want this section here anyway so i'll just delete everything here typically what you would do is pick one of those sections and then delete the little arrow bracket markers around the the remaining bits of code that you

don't want to keep so now that i've made that change and go back to the status buffer it actually automatically stages that change for me because it realizes now that the uh the file no longer has a merge

conflict so to continue with the urea base i press the r key and then r again to continue now let's say uh we get into a situation where we're

like oh crap these changes excuse me are really they're too hard to merge and i don't don't know what to do yet so let me just abort this whole thing you can press a to abort here and then

completely just revert everything that was done by this read base and get back to your original branch state so you don't have to worry if you if you think that something's going to get destroyed just press a to abort here

r a sorry for that in this case i'm going to press r to continue though because i want to continue with that rebase it's going to ask me to

update the commit message uh i don't really care about updating this i'm just going to press ctrl c ctrl c to confirm that and then once that's oops focus issue again ctrl c ctrl c and then

once that's done we're going to be back to the new state of that branch where we have pulled in all of that stuff from origin master and then applied our changes on top of it so

uh let's see uh and now i can force push this branch again so like i mentioned before if you change the history of a branch you have to force push that back to the remote if you've already pushed it once before so i can press capital p

dash f and then p to push that to the config updates branch and now everything will be up to date together uh with the uh head now you can see here we have rebase here on top of origin

master it's in we now have this registered as our upstream branch and that's the reason why you see three entries here in this data section above okay so what if you just want to fetch the changes from the remote repository

without actually pulling them into your current branch if you use the lowercase f character in the status buffer you can do a fetch only without actually affecting your local branch so if i go back into the

dot files repo press lowercase f it brings up the fetch menu and then you have those same keys before the p and the u and the e to say which remote you want to fetch updates from so i'm just going to press

f or sorry p here to effect from origin and we're already up to date on that so we don't have to to pull anything new but that's that is a way if you want to get the latest

new branches or new commits from the remote to use for your local branches uh you can use a lowercase f and then the corresponding letter for the remote you want to pull

from uh let's see anything else here yep so another interesting aspect is you can look at the logs of the commits from the remote repositories after you pull the

latest things so it can be useful to pull uh or to fetch those remotes every once in a while just so you have all the latest uh remote information on your

local copy of the repo all right uh now we're gonna do a couple of remaining things here one is uh discarding unwanted changes so let's say you've been making changes in your repository that you later decide that

you really don't need so instead of going back to those files to undo the changes by hand you can actually use the discard action of the magic status buffer to get rid of those so if you go into the status buffer and

put your cursor on any file hunk or line you can press k to discard that change now uh one thing to to to note here is that

if you use evil collection to have evil key bindings in magit you have to press x instead so instead of k it's x if you use vanilla e max key bindings it's k if you use evil collection it's x i

think it's because uh x is a delete key in vim and k is like kill in emac so that's the reason why that one particular character is different in both of those

so if i go into my emacs.org file and let's say i delete uh this mpv section excuse me and maybe i'll delete the geeks section i don't know i'm feeling a little punchy

today so i can go to uh this mpv section here and i can press x in my case because i'm using evil collection but this would be k if you're not using that

if i press x it's going to ask me here in the echo area discard hunk y or n if i press y it's going to discard that whole honk so i don't have to go to that file and then re-add those changes i can just

go to that specific section of the file in the status buffer and press x or k to just get rid of that change you can also do that for individual lines if i were to select

just this geek's heading and press x or k you press y here and it will discard that region as well which basically reinstates that selection of code

to the state that it was in before same thing also works for an entire file if you press x or k on an entire file it will discard all those changes in that file now this also works for files that have

not yet been checked into source control so if i create a new file called testfile.org hello systemcrafters save that

go back to the status buffer now we see there's an untracked file here that's not a part of the repo if i press k or x here it will ask me if i want to trash the test file or maybe delete testfile.org depending on your

configuration if i press y it will just delete that file so if you have some crafty files that are hanging around that you don't want there anymore you don't want to see them in your status buffer

just use discard to get rid of them and you don't have to go to the command line to delete them or dear red or anything like that you can just do it directly inside of magic uh i'm gonna save this file again so

that we have it again because i'm gonna show another thing you can do in just one second all right so uh the last thing i want to tell you about is adding a file to your.getignore

your.getignore so perhaps you've got a file in a repository that is in the untracked file section but you never want it to ever be checked in you don't want to see it in your magic status buffer anymore

uh you can add it to your dot get ignore file so if you don't know about uh or if you've never seen the dot getting your file before it's basically just a file at the root of your repository that has listings of file patterns for

files that we never want to add to the git repository so that they don't show up in your git status or your diffs or anything like that so if you wanted to add a file to your git ignore you'd

typically have to go edit the file yourself but magic can actually handle this for you so we go back to the status pane excuse me and i refresh it

we'll see that this testfile.org is here if i press the lowercase i key it's going to bring up this gitignore panel at the bottom and we have a few options here one is the t button

that will add it to the top level repo level dot get ignore file which is typically what you want also you can press s to create a get ignore file in the subdirectory of the repository where this file lives which

could be helpful if you have a larger repository that have getting more files at different levels of the repo and also an option to to ignore this file privately which is an interesting thing that i didn't even know about until

recently there's a special file in your get folder of the repository that you can add file patterns to for ignoring files locally so if you don't want to add this

to the actual git ignore file that gets checked into your repository you can use p to privately ignore this file in your own repo can be pretty useful so i'm just going to press t here and

it's going to ask me for what pattern i want to use to ignore this file and by default it's going to pick the appropriate one for the full file name and path however it will also give you some just some suggestions for other patterns you

might want to use based on the file itself so if you want to ignore all org files under this particular path or maybe all org files in the entire project you can select one of these options to do that but in this case we're just

going to select the testfile.org option and now you'll see that magic automatically created this git ignore file for us or no it edited the one that's already there in my case and it added it to the stage changes

folder so if we want to ignore that file permanently we just use cc to commit this and then we can say uh update dot get ignore file and commit that and now we'll never see

that file show up in our git repository again so another really nice feature of magic that makes common everyday operations much easier for you to do all right i think that's everything so

um in the next video i'm going to show you how you can do even more advanced get operations like rebasing cherry picking and managing the ref log if you're a programmer that uses git to collaborate with others on a daily basis

uh these advanced functionalities of magic are going to make your life way way easier i use them all the time and i think it's one of the best parts of magic being able to really efficiently and quickly

do these more advanced operations so if you've got any questions about what we covered today please leave a note in the comments and give me any suggestions for any of this functionality that maybe you feel wasn't covered in depth enough and i'll try to

make another video about it in the future one last thing i want to mention if you are really happy about magic and excited about uh the fact that it exists and it makes things

so much easier for you i highly recommend that you become a sponsor of of jonas bernoulli who is the main developer and maintainer of magic

if you go to github sponsors uh he's there i'll put the link in the show notes but basically um i think jonas is doing this as part of his primary uh the way he makes a living basically

maintaining a variety of emacs packages so i highly recommend becoming a sponsor for jonas on github because he does a lot of really great work for the emacs community i've been a sponsor of jonases for probably i don't know a year and a half

maybe maybe maybe a year but i've been a sponsor of jonas for a while so i've put my money where my mouth is i believe that people should be sponsoring jonas for the work that he's doing on on magic since it is one of the killer

features of emacs for sure all right and uh since we're talking about sponsors i'd like to thank my own sponsors and uh once again the screen is not updated as usual i know i'm very uh unreliable when it comes to this i

apologize for that however these people have decided to sponsor the work that i'm doing making videos about uh can be emacs new geeks etc and i'm very thankful to them for their support if you're interested in supporting the work that i do

uh on these videos definitely check out the links i have below in the description i'm on both github sponsors and patreon there's also a link to paypal for one time tips and if you're not interested in uh supporting the channel in that way

please just click like on the video or any other videos that we post and share them with your friends so that more people can find these videos and we have more people to talk about all this fun stuff with so until next time thanks so much for

watching this video i really appreciate all the interesting magic so hopefully this was helpful and let me know in the comments if there's anything else that you would like to talk about in the future regarding magit

alright thanks a lot and until next time happy hacking we'll see you

Loading...

Loading video analysis...