• WHAT? WHAT IS THIS?

    Woah, woah, calm down.

    Welcome to “Building git: a git tutorial”! This is a series of files and hopefully videos that you can use to get introduced to git. Since git is a topic that is strange to some, and challenging to others, I think this set of articles or videos will help out in bringing them down to Earth.

    The whole approach to this tutorial, guide, book, videoblog, or whatever it becomes, is meant to be “graspable”. If you spot errors, or think of improvements, check the “Contributing” section.

    How was this built?

    This is actually just a huge tree written down in Gingko, and then exported and post processed by a small library I built on my own (gingko-to-markdown). After that, there’s a bot I payed for to commit it to my repository daily.

    [Table of contents for level 1 only]

    #tutorial #gingko

  • Why?

    You and me have probably seen several git tutorials on the internet. And you may agree with me that they jump too quickly into the advanced stuff, and that look too complicated on their own.

    If they don’t, it’s very likely that they don’t present the whole set of features that git has. And this sucks, because git is a wonderful tool, a swiss-army knife of development, and just using it to open your beer is cool, but not cool enough.

    This tutorial pretends to be an easy-to-follow, progressive, light-hearted approach to git that is comprehensible to every level of developers. It’ll start with the basic concepts and later on jump to the real-deal of git usage.

    #needs-proofreading #tutorial

  • About the author

    Since we’re on the subject of what I’d do, let me introduce myself.

    My name is Juan Diego Raimondi, called “JD” by everyone, and I work for a company called MakingSense as a solutions architect. I help support clients and internal or external projects, doing a variety of things to make sure we create things that make sense.

    In case you wondered, yes, the company name itself is a bad pun but we’re that bold and we can afford to do it.

    MakingSense has both products of their own and works with clients in different industries.

    I’m usually doing this stuff on my spare time, but if you do like them and want more of my time into it, contact us and tell us “I want JD to do more open source stuff!”.

    Now, if you want to contact me, personally, you can do so at Twitter.

    Enough about me. Let’s talk about you.

    #needs-proofreading #contact

  • What YOU can expect from this tutorial

    • YOU can expect a simple to follow tutorial starting from very basic concepts
    • YOU can expect a guide that’s extensive, but that you can check in pieces and can use as reference
    • YOU can expect a light hearted approach to it all and to have a few laughs

    Wow, it’s all you, you, you. Stop it already.

    We’re going to start with the basic concepts of VCSs and progressively working our ways towards the absolute best approach that we can, ending up with what git actually is.

    Note that while the tutorial is named “building git”, we’re not actually going to be building it, at least not literally. (It feels SO dumb to use this title while I’m drafting this and already making excuses.) We’re going to figuratively build our way towards what a VCS should do and once it makes sense, git is going to make that dream a reality.

    Finally, you won’t become an expert, and things may not be exactly as accurate. This is on purpose (yeah, right). The point of the tutorial is to bring git’s complexities down to Earth for you to grasp them.

    #needs-proofreading #tutorial #VCS

  • What you should NOT expect from this tutorial

    This is not a list of best practices on git. This is going to simplify its use cases, and even touch on the advanced features, but this is not a comprehensive approach into how to use git for teams or even solo. Different things work for different people and different approaches have different pro-s and con-s. While I’d love to get into them, because I’m as opinionated as someone can be, this is not the place to do it.

    This is not a description of git’s internal mechanisms. git is freaking complicated on the inside. Performance, conflict resolution strategies, cryptography, dark magic… everything here makes for the amazingly complex product that git is. We’re going to approach it from a user’s point of view, not from a git-internals developer’s point of view.

    This is not a guide to using a particular git GUI. IMO, they assume too much, and they widely differ. This guide is going to base itself on the console usage of git. Once you understand what the console does, all GUIs should be very simple to understand.

    #needs-proofreading

  • Assumptions

    I’ll assume that you have some knowledge about computers and some knowledge about code. You don’t need to be really experienced in any programming language, but if seeing code makes your skin crawl, you might not be in the right place.

    I’ll assume that you have git installed and it is already in the PATH for your system, which means that you can start up a console, invoke “git” and it will call the git program. If you don’t have it or it doesn’t work that way, check the installing git tutorial.

    I’ll be using bash files as code examples, because it’s simple to illustrate the point of the changes with them, and because they can be executed to perform some of the tasks that we want to use too. If you don’t get them that’s fine, there will be some explanation of what they do so you can follow along. Windows users, I’m sorry, but batch files are just awful and Powershell is great but I don’t like the syntax. (Plus, you need like a bazillion things before you can run it, and then policies and… no thanks, this is a tutorial on another thing.)

    (Derived from the last point) I’m going to be using the bash shell. Again, there should be nothing crazy here, expect from moving around in repositories and what the prompt tells us. This should be pretty simple to follow and you can expect the same from other OSs, with minor differences that you can adjust changing your configuration.

    #assumptions #configuration #code

  • Tutorial

    Ok, let’s start.

    [Table of contents from level 2]

  • Contributing

    I don’t intend this tutorial to be very seriously taken, but I do intend it to be accurate. If you do find out inconsistencies, errors, or you want to suggest improvements, please do so. This full tutorial, its texts and videos are going to be available as a GitHub repository.

    If you do want to contribute, there are several ways in which you can reach be (Twitter, Email, Facebook, LinkedIn, …), but I suggest that the best approach would be to actually visit the repository and open a ticket or a pull request.

    #needs-proofreading #contributing #contact

  • License

    This work is shared under the CC BY-NC-SA 4.0 license, which basically means you can do whatever you want with it as long as:

    • You don’t commercialize it
    • You don’t remove the attribution to the creators

    Note that these are still possibilities, but the difference is that for it to be legal, you need to request permission from me. No biggie, I’m a reasonable guy, y’know? I’ll probably say yes unless you’re printing copies for the mafia (and you’re not giving me a good share).

    #needs-proofreading #license

  • What we want from a VCS

    We first have to lay down what we expect from a VCS. In case you didn’t know about this, a VCS is a Version Control System. It allows you to maintain different versions of your code, and people use it for progressively tracking changes to what they do, be it code or not. Also, if you didn’t know about it, I’m not angry, just disappointing son.

    VCS are a primordial tool in software development because we mess up. A lot. In order to make sure that the messes are small and controlled, we need to control as well the changes that we’re introducing to a system.

    What we want is:

    • To be able to make one change after the other
    • To be able to go back and forth in between these changes
    • To be able to come up with memorable names for each of these points in time

    #needs-proofreading #vcs

  • Local operations

    As you may imagine, most of our work will happen locally. This is, in our own computer. Later on we’ll learn how to collaborate with others, but, hey, baby steps.

    #needs-finishing

  • Remote repositories

    #needs-finishing

  • Git configuration

    #needs-finishing

    Global, local and effective configuration.

  • Getting gitty with it

    #needs-finishing

  • Advanced stuff

    • Bare repositories
    • Reference log
    • Submodules
    • subtree?
    • bundle?
    • patch?
    • rev-parse
    • update-index

    #needs-finishing

  • One change at a time

    Imagine that you’re making several changes to your document, your code, your sweater knitting, or whatever it is you’re doing. It is always simpler and less error prone to make your changes one at a time, evaluate how everything is going and continue with the next change.

    [image of circles, one after the other, connected with lines, line at the last circle with an arrow that says “you are here”]

    In each of these checkpoints and evaluations, if you happen to find that something’s wrong, you don’t need to backtrace everything that you’ve done so far to find out where you messed up, but rather just from the last checkpoint. This means less wasted hours, less headaches, and a more predictable time usage.

    Making one change at a time is pretty much what any organized person would do, and making these checkpoints come up naturally when you realize that whatever you’ve done so far can be considered one “change” in on itself.

    Now, if there was a way to formalize these checkpoints… maybe committing to what you have done so far…

    #needs-proofreading #changes #commits

  • Going back and forth

    Oops! You messed up. And you’ve been messing up for a while, since you did your checkpoints. You did our evaluations, but still something was wrong from the very start. I could have gotten away with it if it wasn’t for you meddling kids and your dog…

    [image of circles, one after the other, connected with lines, some of those at the left are filled up in green, some others only have the green border. The last filled circle has an arrow to it saying “last good checkpoint”]

    Now, not everything is lost. Our best approach at the moment is to go back as many checkpoints until we are in a way that was still correct. This will allow us to restart from that point without throwing away what has been done since then.

    What we need to do now it so check-out how the situation was at that point in time, and go from there.

    [same as last image of circles, but with a new set of changes branching from the last good known change, with more filling circles]

    #commits #branches #checkout
    #needs-proofreading

  • Naming stuff

    • “Hey Mike, let’s go back to the good checkpoint.”
    • “You mean the last one?”
    • “No, the one we found out was good… until we messed up”
    • “Yesterday or the day before?”
    • “Well… no.. ff..ARRRGHH” explodes

    Naming things is useful. It allows us to refer without confusion to what we mean… unless you mess up with names too, and if that’s the case, I really suggest that you check with someone before having a baby.

    [image of circles, the last known good change now has a sticker onto it that says “payment code done”, and the last one says “last change”]

    #commits #branches #tags
    #needs-proofreading

  • You’re getting ahead of yourself

    Have you guessed it already? Are you thinking in branches, commits and tags? Yes. Then stop. You’re getting ahead of yourself.

    There are a few things we need to introduce first before we get there.

    #commits #branches #tags
    #needs-proofreading

  • Working folder

    Well, what are we going to be tracking changes to? It’s very likely that you’re working with files. So let’s track changes in those.

    As obvious as this sounds, this is actually a design limitation that git has, and purposefully made. There are other changes that you can be making that are not files. Maybe you’re changing the configuration of your system. Maybe you’re tracking physical objects (why are you here, then?). #needs-more-examples

    As such, our VCS (git) is going to operate on files. But operating on all files on the system would be inefficient. Your OS changes a lot of files every time that you do nothing and every time that you do something, so we clearly need to create a better scope for what git will track.

    Let’s decide that git will track changes made to a particular directory and directories inside it. As such, we need to call git and indicate that this is what we want to use as our repository. We’ll call repository the set of files and folders that we’re going to track with this VCS, and we’ll call initializing to this process of starting out a new repository from a common folder.

    #needs-proofreading #working-folder #VCS #changes #initializing

  • Initializing a repository

    If we jump into any directory, we can ask git to initialize it like this:

    > git init
    Initialized empty Git repository in /home/alpha/building-git/.git/

    As you see, git will tell us that it has initialized that repository, and that the folder is now considered a git repository. As well, you can see that it created a .git directory in it. This is what it will use to store it’s inner workings, tracking devices and everything else to take care of this folder for you. This means that it will not mess up your directory existing files at all.

    Similarly, if you want to specify a particular folder to be initialized, you can specify it:

    > git init my-repo
    Initialized empty Git repository in /home/alpha/buiding-git/my-repo/.git/

    Congratulations! You already have created your first repository and are ready to start tracking changes in it.

    #needs-proofreading #initializing #init #repository #filesystem-structure

  • Staging Area / Index

    Hold on. Isn’t it a little bit tyrannical if git were to track everything under that directory? I mean, we could have sensitive files, and I’m not talking files with very breakable feelings, but files with information that you don’t want to be stored forever in a repository.

    For example, you may be developing an invoicing system and you need API codes to interact with a tax calculator. These API codes are private, and you may working with other people and sharing the repository with them. In cases like this, you may not want to share those particular files.

    So, what we need is a way to tell git what we want to include there, instead of everything.

    If you’ve worked into software development or even as a sysadmin, you may have heard of “staging” servers or environments. This is where you get “prepared” to test something out, before you actually commit to making it production. Git has the very same concept, and it’s called the staging area. Because of it’s technical nature, you may sometimes hear it being referred to as the index, but it’s more likely that you’ll see staging area.

    What we want to do is to add the stuff that we want to track to our staging area, and if it all looks correct, we can add it to the repository so it is tracked.

    How do we add files? Well…

    > git add file1.txt
    > git add file2.txt
    > git status
    
    On branch master
    
    Initial commit
    
    Changes to be committed:
      (use "git rm --cached <file>..." to unstage)
    
            new file:   file1.txt
            new file:   file2.txt
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
    
            passwords.txt

    #needs-proofreading #staging-area #index #branches

  • Current status

    WOAH WOAH, what was that?

    Well, we already introduced the concept of files being tracked, files not being tracked, and a staging area. It’s getting a little bit complex, so we don’t want to make this all work from memory, right?

    So, we have a way to check which is our current status, which is appropriately called status. Invoking git status will show a few things:

    [image of a typical status result with pointers and numbers that refer to the enumeration below] #needs-contents

    1. Where are you located in the continuous set of changes that you’re making. (If it has a name, then what name will it have. More on this when we talk about branches and tags.)
    2. What contents does the staging area have.
    3. What files are not currently being tracked.

    This makes it pretty easy to check if you accidentally added a file that you shouldn’t have added, or if you repent from all your sins and you want to take a file out of it.

    This is the chance for you to check that the staging area is correct.

    Not to blow your mind right now (just joking, I totally want to blow your mind right now), but you can actually have different parts of the same file in and out of the staging area. But this is for later, when we talk about interactive-adding and chunk adding.

    #needs-proofreading #status #index #staging-area

  • Commits

    At this point you have added and removed files from your staging area, and you’re ready to commit to those changes. Each commit will represent a snapshot of your repository, and if you lay down the snapshots side by side (which git totally does), you can also think of commits as what changes were performed since the last commit.

    In order to commit the files that you have added to the staging area, you just:

    git commit

    By default, git will open a text editor to ask for a message to be displayed.

    [image of a text editor prompting for a commit message] #needs-contents

    You’ll also be able to review several of the details for the commit, and abort the operation if you want. Enter your commit message, save the file for the editor that git opened, and when you close it, git will do it’s magic.

    [image of what git displays after creating a commit] #needs-contents

    The rest of the development process for working on a feature is a repetition of the last steps.

    • Make changes
    • Reach a checkpoint, verify
    • Add to staging area
    • Commit
    • Rinse and repeat

    Quick adding: adding all

    You’ll find quite often that you have a pretty good knowledge of what your changes are, so you don’t want to add files to the staging area to review them. You just know that you want to add all pending changes to a commit.

    Git has you covered.

    git commit -a

    With this option, you can bypass adding all files to the staging area and have git do that for you.

    Commits are pretty much the central part of git. The bread and butter of this toast that is this VCS. Learn to love them. Put some thought into how you divide your work and how you signal what has been done in them. There will be a lot of pleasure from making your work easy for yourself, or a lot of pain and suffering for making your work difficult.

    #needs-proofreading #commits #staging-area #branches #add #commit-message

  • Ignoring files

    Let’s say that your environment has files that should not be committed to the repository. Files that should be worked on by every developer, because, for example, they contain local configurations, or usernames and passwords, or anything that you don’t want shared in your project history. This is specially useful if your project is open source, because while you want to share your code, you don’t want to share your credentials and accounts. (You’re not so open, are you now?)

    While the usual way of dealing with this is using environment configuration and having your servers do the work, that configuration itself could be anything, from registry entries, to a database, to local files.

    In the case of local files to the project — you guessed it — git will tell you that they are untracked. And if you commit all pending changes, those will go as well.

    Finally, you may have a project build, or compilation, or transpiled files that you don’t want to go along with the source code. And this is perfectly fine and understandable. No, really, you don’t need to explain it. I get you.

    Git allows you to ignore files that comply with an expression. Matching files one by one would be really tedious, but having expression allows for wildcards and the such. It is really not that difficult.

    In order to do this, just create or edit the .gitignore file in the root directory of the repository. Actually, you can have several of these files, each in different directories, and they’ll all be summed up to be applied to the current directory.

    To keep it simple, let’s go with just one:

    thumbs.db              # 1
    /config/passwords.txt  # 2
    *.tmp                  # 3
    /dist/                 # 4
    !/dist/builder.js      # 5

    What this previous example is saying is:

    1. Ignore the thumbs.db file, wherever it is (because we did not specify directories.)
    2. Ignore the file passwords.txt that is present in the config directory. Any other passwords.txt file will not be ignored.
    3. Ignore any file with the extension .tmp.
    4. Ignore the full contents of the directory dist.
    5. Make an exception with the file builder.js inside the dist directory, so do NOT ignore that one.

    If you happen to know what a glob is, you should be on your way. If not, Wikipedia has a nice quick refresher).

    After crafting your file, just save changes into it, and add the file to the index. Yes, the file is a file inside the repository, so it needs to be committed too. While this sounds strange, it is actually great: it means that different points in time can ignore a different set of files. You could create a base configuration, commit it, and then ignore it. This means that whoever makes changes into it, cannot commit changes to it accidentally. (They’d have to un-ignore it first.)

    #needs-proofreading #ignore #glob #index

  • Tags

    Ahh, I see you there, already committing like a crazy fella. Change after change, making your way to completion.

    But life is not linear, is it? Sometimes, your work can deviate in different paths that you want to try before really knowing which of the paths you took is final. Maybe you need a fancy name to refer to the work that you’re doing. Or maybe someone else needs to work on the same code base, but on a different set of changes than you.

    What you want is a level of isolation, and a pointer, some kind of marker that can be referred by name.

    This last point is important: if you some some detail into the commits, you’d see that they can be identified by their hash. But remembering hashes is a pain, specially when they have thirty thousand and twelve digits. (Well, maybe not that much.)

    Enter the tag. You can imagine branches as that: just fancy names or markers that you can give to commits.

    Creating tags is as easy as any other command we have seen so far:

    git tag v0.1

    That’s it! Now you will have a marker that indicates that this commit, with the changes in it included are what you call “v0.1”.

    They don’t need to be versions at all. They can be releases, they can be features being completed, they can be an important point in your project development life, or they can be the maiden name of your mother.

    If you wish to see the list of tags that are present in your repository, you just need to write:

    git tag

    #needs-proofreading #tags

  • Checking out different points in time

    “Ok, so that’s cool”, you say. “I have a bunch of commits, which represent a bunch of changes in time. I also have tags which gives them fancy names. But this is not very useful if I can’t move around.”

    And you’re right, my friend. Moving around is one of the easiest things that you can do in git. And since you want to “check out” how a particular snapshot (commit) looked like, that’s all that it takes to go to it.

    > git checkout v0.1
    Note: checking out 'v0.1'.
    
    (a bunch of text on what you can do)
    
    HEAD is now at 091b0ed... Added files 1 and 2

    What you’re seeing here is pretty much what you would expect. Git tells you “I’m moving here” and then it tells you “I’m here”. It tells you a portion of the commit hash and it shows you the first line of the commit message.

    It tells you that HEAD (the pointer to where you are) is at a particular number. What is that number?

    Well, that number is the hash of the commit. The tag is the commit, because, if you remember, tags were nothing more than a fancy name to one of these snapshots.

    You don’t need to checkout a particular tag. Anything that points to a snapshot will work.

    Using the hash value of the commit:

    > git checkout 091b0ede152bf754f28cf34d17f32990c13e7b4d
    HEAD is now at 091b0ed... Added files 1 and 2

    Using just a portion of it:

    > git checkout 091b0ed
    HEAD is now at 091b0ed... Added files 1 and 2
    > git checkout 091b0ede152bf
    HEAD is now at 091b0ed... Added files 1 and 2
    > git checkout v0.1
    HEAD is now at 091b0ed... Added files 1 and 2

    The text that you saw before will make more sense when we talk about branches, HEAD and the detached HEAD mode.

    #needs-proofreading #HEAD #commits #checkout

  • Branches

    Now that you’re comfortable tagging commits with names, you’d probably seen a problem: you don’t have a way to refer to an in-progress set of changes. For example, you may tag a particular commit as “payment-code-finished” or “v0.1”. But how do you indicate that the set of commits that you’re working on is “new-version” or “cleaning-up-code” or “ongoing-development”?

    This is what branches are for. Branches are just like tags in the sense that they are references to commits, but branches can move around.

    This is how it works: where you are right now is called HEAD. HEAD is pretty much like the HEAD of a printer: it’s the point of reference of the “now” the “where we are” and the “where we can jam up the paper”.

    When you move around, HEAD is there. So, when you make commits, HEAD now points to the new commit.

    Tags point to a commit. And branches point to a commit… or you can make a branch point to HEAD until you move otherwise. Let me show you.

    But first, let’s create a branch:

    $ git branch develop
    $ git status
    On branch develop
    ...
    $ echo "new line" >> file2.txt
    $ git add file2.txt
    $ git commit -m "Added new line"
    [develop 5d0a91a] Added new line
    $ git status
    On branch develop
    ...
    `

    So, as you can see, as long as we’re “standing” on a branch, making commits or updates to it will update the branch as well, which means that the branch is tracking our “HEAD” position.

    Let’s walk step by step into what happened after executing each command:

    $ git branch develop

    [image, branch named develop pointing to a specific commit, a signaler indicating that our HEAD is there too]

    $ echo "new line" >> file2.txt

    [same image as before, but now indicating that there is something into a “working area”, mark it in a different color to indicate that is it not a commit]

    $ git add file2.txt

    [same image as before, but now the working area is colored in a different way and it is labeled staging area]

    $ git commit -m "Added new line"

    [same image as before, but without working area or staging area, now there is a new commit and it is labeled with the message. The branch is now pointing to it and the HEAD is now pointing to it.]

    I’ve skipped over the git status commands because they don’t perform any change on the structure of the tree.

    Detached head mode

    Now, you’ve seen how the branch that we’re in will follow around our HEAD pointer. However, it is possible to override this behavior if we were to not use a branch. For example, let’s continue from the very same commit that we just did, and we’ll make another commit where the develop branch won’t be affected.

    $ git checkout 5d0a91a
    You are in 'detached HEAD' state.
    ...
    
    $ echo "new line 2" >> file2.txt
    
    $ git commit -a -m "Added another new line"
    [detached HEAD ed29c4b] Added another new line
    
    $ git log --oneline
    ed29c4b Added another new line
    5d0a91a Added new line
    c354288 Change 1
    091b0ed Added files 1 and 2
    
    $ git checkout develop
    Warning: you are leaving 1 commit behind, not connected to
    any of your branches:
    
      ed29c4b Added another new line
    
    If you want to keep them by creating a new branch, this may be a good time
    to do so with:
    
     git branch new_branch_name ed29c4b
    
    $ git log --oneline
    5d0a91a Added new line
    c354288 Change 1
    091b0ed Added files 1 and 2

    As you can see, we went “back” to the develop branch, and that meant leaving our commit abandoned. Since nothing is pointing to this commit, eventually git’s internal garbage collector will pick it up and remove it altogether. Git warns us about this and even gives us some instructions into how to create a branch that points to it.

    #needs-finishing #branches #log #checkout #references #detached-head-mode #commit

  • Stash

    At some point you may want to suspend your work and go back to the latest commit. Or switch to another branch. Whatever the reason, you want to leave your current changes behind, but you don’t want to lose them, and you don’t want to commit them either. Maybe you were just experimenting. Maybe it’s a work in progress. The world may never know.

    Whatever the reason, git has you covered.

    The stash is yet another storage method that git contains, this one being purely local (so you won’t be able to push it to a remote repository).

    All you need to do to save your work to the stash is

    git stash

    And when you’re ready to come back to it:

    git stash pop

    A fun trick is that you can even pop the stash when you’re not in the same commit where you saved it (pushed it). This means you can move your current work around without having to commit it.

    git stash
    git checkout another-branch
    git pop

    #stash #stash-pop

  • Conflict resolution

    You know what conflicts are, right? No? I’ll bash your head and we’ll see.

    Whenever you’ve switched to another branch, or applied changes from stash (or from other places, as we’ll see), you’ll may get into conflicts. But what are conflicts in the first place?

    Conflicts is git trying to apply two different changes to the same place in the same file at the same time.

    Follow up this set of commands as an exercise.

    # our base file to work with
    git checkout -b baseBranch
    echo "Line 1" >> myFile.txt
    echo "Line 2" >> myFile.txt
    git add myFile.txt
    git commit -m "Base commit"
    
    # first set of changes from base
    git checkout -b branch1
    sed -i '/Line 2/Line 2 Modified 1/' myFile.txt
    git add myFile.txt
    git commit -m "Commit 1"
    
    # second set of changes from base
    git checkout baseBranch
    git checkout -b branch2
    sed -i '/Line 2/Line 2 Modified 2/' myFile.txt
    git add myFile.txt
    git commit -m "Commit 2"
    
    # combine those changes -- uh oh
    git merge branch1

    #needs-finishing #conflicts #merging

  • Annotated tags

    As you know by know, a tag is pretty much tag: a particular note, an indicator, something on that particular commit. For some operations, you will need something more reliable, something that actually has special information about the state of the repository at that point.

    Come into scene: annotated tags.

    For example, GitHub uses annotated tags to differentiate releases in a particular repository.

    Annotated tags have everything that a regular tag has, plus:

    • checksum of the contents
    • tag author name, email
    • tag date
    • message
    • signature verifiable with GPG

    So you can see why for particular purposes you’d prefer an annotated tag.

    Creating one is as simple as it gets:

    git tag -a v0.1 -m "First test version"

    #needs-proofreading #tags #annotated-tags

{"cards":[{"_id":"6102bbc655726f6efe000030","treeId":"6101d4901a5d3006df00001d","seq":6545792,"position":1,"parentId":null,"content":"# WHAT? WHAT IS THIS?\n\nWoah, woah, calm down.\n\nWelcome to \"Building git: a git tutorial\"! This is a series of files and hopefully videos that you can use to get introduced to git. Since git is a topic that is strange to some, and challenging to others, I think this set of articles or videos will help out in bringing them down to Earth.\n\nThe whole approach to this tutorial, guide, book, videoblog, or whatever it becomes, is meant to be \"graspable\". If you spot errors, or think of improvements, check the \"Contributing\" section.\n\n## How was this built?\n\nThis is actually just a huge _tree_ written down in [Gingko](https://gingkoapp.com/building-git-a-git-tutorial), and then exported and post processed by a small library I built on my own ([gingko-to-markdown](https://github.com/AlphaGit/gingko-to-markdown)). After that, there's a bot I payed for to commit it to my repository daily.\n\n[Table of contents for level 1 only]\n\n#tutorial #gingko"},{"_id":"610200c11a5d3006df000037","treeId":"6101d4901a5d3006df00001d","seq":6545794,"position":2,"parentId":null,"content":"# Why?\n\nYou and me have probably seen several git tutorials on the internet. And you may agree with me that they jump too quickly into the advanced stuff, and that look too complicated on their own.\n\nIf they don't, it's very likely that they don't present the whole set of features that git has. And this sucks, because git is a wonderful tool, a swiss-army knife of development, and just using it to open your beer is cool, but not cool enough.\n\nThis tutorial pretends to be an easy-to-follow, progressive, light-hearted approach to git that is comprehensible to every level of developers. It'll start with the basic concepts and later on jump to the real-deal of git usage.\n\n#needs-proofreading #tutorial"},{"_id":"6102019b1a5d3006df000038","treeId":"6101d4901a5d3006df00001d","seq":6545810,"position":3,"parentId":null,"content":"# About the author\n\nSince we're on the subject of what I'd do, let me introduce myself.\n\nMy name is Juan Diego Raimondi, called \"JD\" by everyone, and I work for a company called MakingSense as a solutions architect. I help support clients and internal or external projects, doing a variety of things to make sure we create things that _make sense_.\n\nIn case you wondered, yes, the company name itself is a bad pun but we're that bold and we can afford to do it.\n\nMakingSense has both products of their own and works with clients in different industries.\n\nI'm usually doing this stuff on my spare time, but if you do like them and want more of my time into it, [contact us](http://makingsense.com/talk-to-us) and tell us \"I want JD to do more open source stuff!\".\n\nNow, if you want to contact me, personally, you can do so at [Twitter](http://www.twitter.com/AlphaTwi).\n\nEnough about me. Let's talk about you.\n\n#needs-proofreading #contact"},{"_id":"610202041a5d3006df00003a","treeId":"6101d4901a5d3006df00001d","seq":6545800,"position":4,"parentId":null,"content":"# What YOU can expect from this tutorial\n\n* YOU can expect a simple to follow tutorial starting from very basic concepts\n* YOU can expect a guide that's extensive, but that you can check in pieces and can use as reference\n* YOU can expect a light hearted approach to it all and to have a few laughs\n\nWow, it's all you, you, you. Stop it already.\n\nWe're going to start with the basic concepts of VCSs and progressively working our ways towards the absolute best approach that we can, ending up with what git actually is.\n\nNote that while the tutorial is named \"building git\", we're not actually going to be building it, at least not literally. (It feels SO dumb to use this title while I'm drafting this and already making excuses.) We're going to figuratively build our way towards what a VCS should do and once it makes sense, git is going to make that dream a reality.\n\nFinally, you won't become an expert, and things may not be exactly as accurate. This is on purpose (yeah, right). The point of the tutorial is to bring git's complexities down to Earth for you to grasp them.\n\n#needs-proofreading #tutorial #VCS"},{"_id":"61028e0a55726f6efe000027","treeId":"6101d4901a5d3006df00001d","seq":5690459,"position":4.5,"parentId":null,"content":"# What you should NOT expect from this tutorial\n\n**This is not a list of best practices on git.** This is going to simplify its use cases, and even touch on the advanced features, but this is not a comprehensive approach into how to use git for teams or even solo. Different things work for different people and different approaches have different pro-s and con-s. While I'd love to get into them, because I'm as opinionated as someone can be, this is not the place to do it.\n\n**This is not a description of git's internal mechanisms.** git _is_ freaking complicated on the inside. Performance, conflict resolution strategies, cryptography, dark magic... everything here makes for the amazingly complex product that git is. We're going to approach it from a user's point of view, not from a git-internals developer's point of view.\n\n**This is not a guide to using a particular git GUI.** IMO, they assume too much, and they widely differ. This guide is going to base itself on the console usage of git. Once you understand what the console does, all GUIs should be very simple to understand.\n\n#needs-proofreading"},{"_id":"6102a75055726f6efe00002b","treeId":"6101d4901a5d3006df00001d","seq":6545805,"position":4.75,"parentId":null,"content":"# Assumptions\n\n**I'll assume that you have some knowledge about computers and some knowledge about code.** You don't need to be really experienced in any programming language, but if seeing code makes your skin crawl, you might not be in the right place.\n\n**I'll assume that you have git installed and it is already in the PATH for your system,** which means that you can start up a console, invoke \"git\" and it will call the git program. If you don't have it or it doesn't work that way, check the [installing git tutorial](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).\n\n**I'll be using bash files as code examples**, because it's simple to illustrate the point of the changes with them, and because they can be executed to perform some of the tasks that we want to use too. If you don't get them that's fine, there will be some explanation of what they do so you can follow along. Windows users, I'm sorry, but batch files are just awful and Powershell is great but I don't like the syntax. (Plus, you need like a bazillion things before you can run it, and then policies and... no thanks, this is a tutorial on another thing.)\n\n(Derived from the last point) **I'm going to be using the bash shell.** Again, there should be nothing crazy here, expect from moving around in repositories and what the prompt tells us. This should be pretty simple to follow and you can expect the same from other OSs, with minor differences that you can adjust changing your configuration.\n\n#assumptions #configuration #code"},{"_id":"6101d49f1a5d3006df00001f","treeId":"6101d4901a5d3006df00001d","seq":5689945,"position":5.25,"parentId":null,"content":"# Tutorial\n\nOk, let's start.\n\n[Table of contents from level 2]","deleted":false},{"_id":"6101d7e61a5d3006df000023","treeId":"6101d4901a5d3006df00001d","seq":6545824,"position":3,"parentId":"6101d49f1a5d3006df00001f","content":"## What we want from a VCS\n\nWe first have to lay down what we expect from a VCS. In case you didn't know about this, a VCS is a Version Control System. It allows you to maintain different versions of your code, and people use it for progressively tracking changes to what they do, be it code or not. Also, if you didn't know about it, I'm not angry, just disappointing son.\n\nVCS are a primordial tool in software development because we mess up. A lot. In order to make sure that the messes are small and controlled, we need to control as well the changes that we're introducing to a system.\n\nWhat we want is:\n\n* To be able to make one change after the other\n* To be able to go back and forth in between these changes\n* To be able to come up with memorable names for each of these points in time\n\n#needs-proofreading #vcs"},{"_id":"61025633fca85a3f8b000021","treeId":"6101d4901a5d3006df00001d","seq":6545827,"position":5,"parentId":"6101d7e61a5d3006df000023","content":"### One change at a time\n\nImagine that you're making several changes to your document, your code, your sweater knitting, or whatever it is you're doing. It is always simpler and less error prone to make your changes one at a time, evaluate how everything is going and continue with the next change.\n\n[image of circles, one after the other, connected with lines, line at the last circle with an arrow that says \"you are here\"]\n\nIn each of these checkpoints and evaluations, if you happen to find that something's wrong, you don't need to backtrace everything that you've done so far to find out where you messed up, but rather just from the last checkpoint. This means less wasted hours, less headaches, and a more predictable time usage.\n\nMaking one change at a time is pretty much what any organized person would do, and making these checkpoints come up naturally when you realize that whatever you've done so far can be considered one \"change\" in on itself.\n\nNow, if there was a way to formalize these checkpoints... maybe _committing_ to what you have done so far...\n\n#needs-proofreading #changes #commits"},{"_id":"61025d4d55726f6efe000022","treeId":"6101d4901a5d3006df00001d","seq":5690423,"position":6,"parentId":"6101d7e61a5d3006df000023","content":"### Going back and forth\n\nOops! You messed up. And you've been messing up for a while, since you did your checkpoints. You did our evaluations, but still something was wrong from the very start. I could have gotten away with it if it wasn't for you meddling kids and your dog...\n\n[image of circles, one after the other, connected with lines, some of those at the left are filled up in green, some others only have the green border. The last filled circle has an arrow to it saying \"last good checkpoint\"]\n\nNow, not everything is lost. Our best approach at the moment is to go back as many checkpoints until we are in a way that was still correct. This will allow us to restart from that point without throwing away what has been done since then.\n\nWhat we need to do now it so _check-out_ how the situation was at that point in time, and go from there.\n\n[same as last image of circles, but with a new set of changes branching from the last good known change, with more filling circles]\n\n#commits #branches #checkout\n#needs-proofreading"},{"_id":"6102686855726f6efe000023","treeId":"6101d4901a5d3006df00001d","seq":5689256,"position":7,"parentId":"6101d7e61a5d3006df000023","content":"### Naming stuff\n\n>- \"Hey Mike, let's go back to the good checkpoint.\"\n>- \"You mean the last one?\"\n>- \"No, the one we found out was good... until we messed up\"\n>- \"Yesterday or the day before?\"\n>- \"Well... no.. ff..ARRRGHH\" *explodes*\n\nNaming things is useful. It allows us to refer without confusion to what we mean... unless you mess up with names too, and if that's the case, I really suggest that you check with someone before having a baby.\n\n[image of circles, the last known good change now has a sticker onto it that says \"payment code done\", and the last one says \"last change\"]\n\n#commits #branches #tags\n#needs-proofreading"},{"_id":"61027dc055726f6efe000026","treeId":"6101d4901a5d3006df00001d","seq":5689257,"position":8,"parentId":"6101d7e61a5d3006df000023","content":"### You're getting ahead of yourself\n\nHave you guessed it already? Are you thinking in branches, commits and tags? Yes. Then stop. You're getting ahead of yourself.\n\nThere are a few things we need to introduce first before we get there.\n\n#commits #branches #tags\n#needs-proofreading"},{"_id":"61034f1755726f6efe000035","treeId":"6101d4901a5d3006df00001d","seq":6030225,"position":4.4375,"parentId":"6101d49f1a5d3006df00001f","content":"## Local operations\n\nAs you may imagine, most of our work will happen locally. This is, in our own computer. Later on we'll learn how to collaborate with others, but, hey, baby steps.\n\n#needs-finishing"},{"_id":"610204891a5d3006df00003d","treeId":"6101d4901a5d3006df00001d","seq":6545829,"position":0.5,"parentId":"61034f1755726f6efe000035","content":"## Working folder\n\nWell, what are we going to be tracking changes to? It's very likely that you're working with files. So let's track changes in those.\n\nAs obvious as this sounds, this is actually a design limitation that git has, and purposefully made. There are other changes that you can be making that are not files. Maybe you're changing the configuration of your system. Maybe you're tracking physical objects (why are you here, then?). #needs-more-examples\n\nAs such, our VCS (git) is going to operate on files. But operating on _all_ files on the system would be inefficient. Your OS changes a lot of files every time that you do nothing and every time that you do something, so we clearly need to create a better scope for what git will track.\n\nLet's decide that git will track changes made to a particular directory and directories inside it. As such, we need to call git and indicate that this is what we want to use as our **repository**. We'll call **repository** the set of files and folders that we're going to track with this VCS, and we'll call **initializing** to this process of starting out a new repository from a common folder.\n\n#needs-proofreading #working-folder #VCS #changes #initializing"},{"_id":"6102a61655726f6efe00002a","treeId":"6101d4901a5d3006df00001d","seq":6545833,"position":1,"parentId":"61034f1755726f6efe000035","content":"## Initializing a repository\n\nIf we jump into any directory, we can ask git to initialize it like this:\n\n```console\n> git init\nInitialized empty Git repository in /home/alpha/building-git/.git/\n```\n\nAs you see, git will tell us that it has initialized that repository, and that the folder is now considered a git repository. As well, you can see that it created a `.git` directory in it. This is what it will use to store it's inner workings, tracking devices and everything else to take care of this folder for you. This means that it will not mess up your directory existing files at all.\n\nSimilarly, if you want to specify a particular folder to be initialized, you can specify it:\n\n```console\n> git init my-repo\nInitialized empty Git repository in /home/alpha/buiding-git/my-repo/.git/\n```\n\nCongratulations! You already have created your first repository and are ready to start tracking changes in it.\n\n#needs-proofreading #initializing #init #repository #filesystem-structure"},{"_id":"610204c01a5d3006df00003e","treeId":"6101d4901a5d3006df00001d","seq":6545837,"position":2,"parentId":"61034f1755726f6efe000035","content":"## Staging Area / Index\n\nHold on. Isn't it a little bit tyrannical if git were to track _everything_ under that directory? I mean, we could have sensitive files, and I'm not talking files with very breakable feelings, but files with information that you don't want to be stored forever in a repository.\n\nFor example, you may be developing an invoicing system and you need API codes to interact with a tax calculator. These API codes are private, and you may working with other people and sharing the repository with them. In cases like this, you may not want to share those particular files.\n\nSo, what we need is a way to tell git what we want to include there, instead of everything.\n\nIf you've worked into software development or even as a sysadmin, you may have heard of \"staging\" servers or environments. This is where you get \"prepared\" to test something out, before you actually _commit_ to making it production. Git has the very same concept, and it's called the *staging area*. Because of it's technical nature, you may sometimes hear it being referred to as the *index*, but it's more likely that you'll see *staging area*.\n\nWhat we want to do is to add the stuff that we want to track to our staging area, and if it all looks correct, we can add it to the repository so it is tracked.\n\nHow do we **add** files? Well...\n\n```console\n> git add file1.txt\n> git add file2.txt\n> git status\n\nOn branch master\n\nInitial commit\n\nChanges to be committed:\n (use \"git rm --cached <file>...\" to unstage)\n\n new file: file1.txt\n new file: file2.txt\n\nUntracked files:\n (use \"git add <file>...\" to include in what will be committed)\n\n passwords.txt\n\n```\n\n#needs-proofreading #staging-area #index #branches"},{"_id":"61032db555726f6efe000033","treeId":"6101d4901a5d3006df00001d","seq":6545841,"position":3,"parentId":"61034f1755726f6efe000035","content":"## Current status\n\nWOAH WOAH, what was that?\n\nWell, we already introduced the concept of files being tracked, files not being tracked, and a staging area. It's getting a little bit complex, so we don't want to make this all work from memory, right?\n\nSo, we have a way to check which is our current status, which is appropriately called `status`. Invoking git status will show a few things:\n\n[image of a typical status result with pointers and numbers that refer to the enumeration below] #needs-contents\n\n1. Where are you located in the continuous set of changes that you're making. (If it has a name, then what name will it have. More on this when we talk about branches and tags.)\n2. What contents does the staging area have.\n3. What files are not currently being tracked.\n\nThis makes it pretty easy to check if you accidentally added a file that you shouldn't have added, or if you repent from all your sins and you want to take a file out of it.\n\nThis is the chance for you to check that the staging area is correct.\n\nNot to blow your mind right now (just joking, I totally want to blow your mind right now), but you can actually have different parts of the same file in and out of the staging area. But this is for later, when we talk about interactive-adding and chunk adding.\n\n#needs-proofreading #status #index #staging-area"},{"_id":"610205041a5d3006df00003f","treeId":"6101d4901a5d3006df00001d","seq":6545844,"position":4,"parentId":"61034f1755726f6efe000035","content":"## Commits\n\nAt this point you have added and removed files from your staging area, and you're ready to _commit_ to those changes. Each commit will represent a snapshot of your repository, and if you lay down the snapshots side by side (which git totally does), you can also think of commits as what changes were performed since the last commit.\n\nIn order to commit the files that you have added to the staging area, you just:\n\n```console\ngit commit\n```\n\nBy default, git will open a text editor to ask for a message to be displayed.\n\n[image of a text editor prompting for a commit message] #needs-contents\n\nYou'll also be able to review several of the details for the commit, and abort the operation if you want. Enter your commit message, save the file for the editor that git opened, and when you close it, git will do it's magic.\n\n[image of what git displays after creating a commit] #needs-contents\n\nThe rest of the development process for working on a feature is a repetition of the last steps.\n\n* Make changes\n* Reach a checkpoint, verify\n* Add to staging area\n* Commit\n* Rinse and repeat\n\n### Quick adding: adding all\n\nYou'll find quite often that you have a pretty good knowledge of what your changes are, so you don't want to add files to the staging area to review them. You just _know_ that you want to add all pending changes to a commit.\n\nGit has you covered. \n\n```console\ngit commit -a\n```\n\nWith this option, you can bypass adding all files to the staging area and have git do that for you.\n\nCommits are pretty much the central part of git. The bread and butter of this toast that is this VCS. Learn to love them. Put some thought into how you divide your work and how you signal what has been done in them. There will be a lot of pleasure from making your work easy for yourself, or a lot of pain and suffering for making your work difficult.\n\n#needs-proofreading #commits #staging-area #branches #add #commit-message"},{"_id":"61029d9555726f6efe000029","treeId":"6101d4901a5d3006df00001d","seq":6545848,"position":5,"parentId":"61034f1755726f6efe000035","content":"## Ignoring files\n\nLet's say that your environment has files that should not be committed to the repository. Files that should be worked on by every developer, because, for example, they contain local configurations, or usernames and passwords, or anything that you don't want shared in your project history. This is specially useful if your project is open source, because while you want to share your code, you don't want to share your credentials and accounts. (You're not so open, are you now?)\n\nWhile the usual way of dealing with this is using environment configuration and having your servers do the work, that configuration itself could be anything, from registry entries, to a database, to local files.\n\nIn the case of local files to the project -- you guessed it -- git will tell you that they are untracked. And if you commit all pending changes, those will go as well.\n\nFinally, you may have a project build, or compilation, or transpiled files that you don't want to go along with the source code. And this is perfectly fine and understandable. No, really, you don't need to explain it. I get you.\n\nGit allows you to ignore files that comply with an expression. Matching files one by one would be really tedious, but having expression allows for wildcards and the such. It is really not that difficult.\n\nIn order to do this, just create or edit the `.gitignore` file in the root directory of the repository. Actually, you can have several of these files, each in different directories, and they'll all be summed up to be applied to the current directory.\n\nTo keep it simple, let's go with just one:\n\n```text\nthumbs.db # 1\n/config/passwords.txt # 2\n*.tmp # 3\n/dist/ # 4\n!/dist/builder.js # 5\n```\n\nWhat this previous example is saying is:\n\n1. Ignore the `thumbs.db` file, wherever it is (because we did not specify directories.)\n2. Ignore the file `passwords.txt` that is present in the `config` directory. Any other `passwords.txt` file will not be ignored.\n3. Ignore any file with the extension `.tmp`.\n4. Ignore the full contents of the directory `dist`.\n5. Make an exception with the file `builder.js` inside the `dist` directory, so do NOT ignore that one.\n\nIf you happen to know what a glob is, you should be on your way. If not, [Wikipedia has a nice quick refresher](https://en.wikipedia.org/wiki/Glob_(programming)).\n\nAfter crafting your file, just save changes into it, and add the file to the index. Yes, the file is a file inside the repository, so it needs to be committed too. While this sounds strange, it is actually great: it means that different points in time can ignore a different set of files. You could create a base configuration, commit it, and then ignore it. This means that whoever makes changes into it, cannot commit changes to it accidentally. (They'd have to un-ignore it first.)\n\n#needs-proofreading #ignore #glob #index"},{"_id":"610205461a5d3006df000041","treeId":"6101d4901a5d3006df00001d","seq":6545851,"position":5.5,"parentId":"61034f1755726f6efe000035","content":"## Tags\n\nAhh, I see you there, already committing like a crazy fella. Change after change, making your way to completion.\n\nBut life is not linear, is it? Sometimes, your work can deviate in different paths that you want to try before really knowing which of the paths you took is final. Maybe you need a fancy name to refer to the work that you're doing. Or maybe someone else needs to work on the same code base, but on a different set of changes than you.\n\nWhat you want is a level of isolation, and a pointer, some kind of marker that can be referred by name.\n\nThis last point is important: if you some some detail into the commits, you'd see that they can be identified by their hash. But remembering hashes is a pain, specially when they have thirty thousand and twelve digits. (Well, maybe not that much.)\n\nEnter the tag. You can imagine branches as that: just fancy names or markers that you can give to commits.\n\nCreating tags is as easy as any other command we have seen so far:\n\n```console\ngit tag v0.1\n```\n\nThat's it! Now you will have a marker that indicates that this commit, with the changes in it included are what you call \"v0.1\".\n\nThey don't need to be versions at all. They can be releases, they can be features being completed, they can be an important point in your project development life, or they can be the maiden name of your mother.\n\nIf you wish to see the list of tags that are present in your repository, you just need to write:\n\n```console\ngit tag\n```\n\n#needs-proofreading #tags"},{"_id":"6102abff55726f6efe00002f","treeId":"6101d4901a5d3006df00001d","seq":6545852,"position":1,"parentId":"610205461a5d3006df000041","content":"### Annotated tags\n\nAs you know by know, a tag is pretty much tag: a particular note, an indicator, _something_ on that particular commit. For some operations, you will need something more reliable, something that actually has special information about the state of the repository at that point.\n\nCome into scene: _annotated tags_.\n\nFor example, GitHub uses annotated tags to differentiate releases in a particular repository.\n\nAnnotated tags have everything that a regular tag has, plus:\n\n- checksum of the contents\n- tag author name, email\n- tag date\n- message\n- signature verifiable with GPG\n\nSo you can see why for particular purposes you'd prefer an annotated tag.\n\nCreating one is as simple as it gets:\n\n```console\ngit tag -a v0.1 -m \"First test version\"\n```\n\n#needs-proofreading #tags #annotated-tags"},{"_id":"6111bff03c030b99b4000032","treeId":"6101d4901a5d3006df00001d","seq":6545856,"position":5.75,"parentId":"61034f1755726f6efe000035","content":"## Checking out different points in time\n\n\"Ok, so that's cool\", you say. \"I have a bunch of commits, which represent a bunch of changes in time. I also have tags which gives them fancy names. But this is not very useful if I can't move around.\"\n\nAnd you're right, my friend. Moving around is one of the easiest things that you can do in git. And since you want to \"check out\" how a particular snapshot (commit) looked like, that's all that it takes to go to it.\n\n```console\n> git checkout v0.1\nNote: checking out 'v0.1'.\n\n(a bunch of text on what you can do)\n\nHEAD is now at 091b0ed... Added files 1 and 2\n```\n\nWhat you're seeing here is pretty much what you would expect. Git tells you \"I'm moving here\" and then it tells you \"I'm here\". It tells you a portion of the commit hash and it shows you the first line of the commit message.\n\nIt tells you that `HEAD` (the pointer to where you are) is at a particular number. What is that number?\n\nWell, that number is the hash of the commit. The tag is the commit, because, if you remember, tags were nothing more than a fancy name to one of these snapshots.\n\nYou don't need to checkout a particular tag. Anything that points to a snapshot will work.\n\nUsing the hash value of the commit:\n\n```console\n> git checkout 091b0ede152bf754f28cf34d17f32990c13e7b4d\nHEAD is now at 091b0ed... Added files 1 and 2\n```\n\nUsing just a portion of it:\n\n```console\n> git checkout 091b0ed\nHEAD is now at 091b0ed... Added files 1 and 2\n> git checkout 091b0ede152bf\nHEAD is now at 091b0ed... Added files 1 and 2\n> git checkout v0.1\nHEAD is now at 091b0ed... Added files 1 and 2\n```\n\nThe text that you saw before will make more sense when we talk about branches, HEAD and the detached HEAD mode.\n\n#needs-proofreading #HEAD #commits #checkout"},{"_id":"610205271a5d3006df000040","treeId":"6101d4901a5d3006df00001d","seq":6545860,"position":6,"parentId":"61034f1755726f6efe000035","content":"## Branches\n\nNow that you're comfortable tagging commits with names, you'd probably seen a problem: you don't have a way to refer to an in-progress set of changes. For example, you may tag a particular commit as \"payment-code-finished\" or \"v0.1\". But how do you indicate that the set of commits that you're working on is \"new-version\" or \"cleaning-up-code\" or \"ongoing-development\"?\n\nThis is what **branches** are for. Branches are just like tags in the sense that they are references to commits, but branches can move around.\n\nThis is how it works: where you are right now is called HEAD. HEAD is pretty much like the HEAD of a printer: it's the point of reference of the \"now\" the \"where we are\" and the \"where we can jam up the paper\".\n\nWhen you move around, HEAD is there. So, when you make commits, HEAD now points to the new commit.\n\nTags point to a commit. And branches point to a commit... or you can make a branch point to HEAD until you move otherwise. Let me show you.\n\nBut first, let's create a branch:\n\n```console\n$ git branch develop\n$ git status\nOn branch develop\n...\n$ echo \"new line\" >> file2.txt\n$ git add file2.txt\n$ git commit -m \"Added new line\"\n[develop 5d0a91a] Added new line\n$ git status\nOn branch develop\n...\n```` \n\nSo, as you can see, as long as we're \"standing\" on a branch, making commits or updates to it will update the branch as well, which means that the branch is tracking our \"HEAD\" position.\n\nLet's walk step by step into what happened after executing each command:\n\n```console\n$ git branch develop\n```\n\n[image, branch named develop pointing to a specific commit, a signaler indicating that our HEAD is there too]\n\n```console\n$ echo \"new line\" >> file2.txt\n```\n\n[same image as before, but now indicating that there is something into a \"working area\", mark it in a different color to indicate that is it not a commit]\n\n```console\n$ git add file2.txt\n```\n\n[same image as before, but now the working area is colored in a different way and it is labeled staging area]\n\n```console\n$ git commit -m \"Added new line\"\n```\n\n[same image as before, but without working area or staging area, now there is a new commit and it is labeled with the message. The branch is now pointing to it and the HEAD is now pointing to it.]\n\nI've skipped over the `git status` commands because they don't perform any change on the structure of the tree.\n\n### Detached head mode\n\nNow, you've seen how the branch that we're in will follow around our HEAD pointer. However, it is possible to override this behavior if we were to not use a branch. For example, let's continue from the very same commit that we just did, and we'll make another commit where the `develop` branch won't be affected.\n\n```console\n$ git checkout 5d0a91a\nYou are in 'detached HEAD' state.\n...\n\n$ echo \"new line 2\" >> file2.txt\n\n$ git commit -a -m \"Added another new line\"\n[detached HEAD ed29c4b] Added another new line\n\n$ git log --oneline\ned29c4b Added another new line\n5d0a91a Added new line\nc354288 Change 1\n091b0ed Added files 1 and 2\n\n$ git checkout develop\nWarning: you are leaving 1 commit behind, not connected to\nany of your branches:\n\n ed29c4b Added another new line\n\nIf you want to keep them by creating a new branch, this may be a good time\nto do so with:\n\n git branch new_branch_name ed29c4b\n\n$ git log --oneline\n5d0a91a Added new line\nc354288 Change 1\n091b0ed Added files 1 and 2\n```\n\nAs you can see, we went \"back\" to the `develop` branch, and that meant leaving our commit abandoned. Since nothing is pointing to this commit, eventually git's internal garbage collector will pick it up and remove it altogether. Git warns us about this and even gives us some instructions into how to create a branch that points to it.\n\n#needs-finishing #branches #log #checkout #references #detached-head-mode #commit"},{"_id":"610252f2fca85a3f8b000020","treeId":"6101d4901a5d3006df00001d","seq":6756726,"position":8,"parentId":"61034f1755726f6efe000035","content":"## Stash\n\nAt some point you may want to suspend your work and go back to the latest commit. Or switch to another branch. Whatever the reason, you want to leave your current changes behind, but you don't want to lose them, and you don't want to commit them either. Maybe you were just experimenting. Maybe it's a work in progress. The world may never know.\n\nWhatever the reason, git has you covered.\n\nThe stash is yet another storage method that git contains, this one being purely local (so you won't be able to push it to a remote repository).\n\nAll you need to do to save your work to the stash is\n\n```\ngit stash\n```\n\nAnd when you're ready to come back to it:\n\n```\ngit stash pop\n```\n\nA fun trick is that you can even pop the stash when you're not in the same commit where you saved it (pushed it). This means you can move your current work around without having to commit it.\n\n```\ngit stash\ngit checkout another-branch\ngit pop\n```\n\n#stash #stash-pop"},{"_id":"610205641a5d3006df000042","treeId":"6101d4901a5d3006df00001d","seq":6756734,"position":9,"parentId":"61034f1755726f6efe000035","content":"## Merging\n\n#needs-finishing #merging"},{"_id":"6695ab352eabd6c835000033","treeId":"6101d4901a5d3006df00001d","seq":6756736,"position":9.5,"parentId":"61034f1755726f6efe000035","content":"## Conflict resolution\n\nYou know what conflicts are, right? No? I'll bash your head and we'll see.\n\nWhenever you've switched to another branch, or applied changes from stash (or from other places, as we'll see), you'll may get into conflicts. But what are conflicts in the first place?\n\nConflicts is git trying to apply two different changes to the same place in the same file at the same time.\n\nFollow up this set of commands as an exercise.\n\n```\n# our base file to work with\ngit checkout -b baseBranch\necho \"Line 1\" >> myFile.txt\necho \"Line 2\" >> myFile.txt\ngit add myFile.txt\ngit commit -m \"Base commit\"\n\n# first set of changes from base\ngit checkout -b branch1\nsed -i '/Line 2/Line 2 Modified 1/' myFile.txt\ngit add myFile.txt\ngit commit -m \"Commit 1\"\n\n# second set of changes from base\ngit checkout baseBranch\ngit checkout -b branch2\nsed -i '/Line 2/Line 2 Modified 2/' myFile.txt\ngit add myFile.txt\ngit commit -m \"Commit 2\"\n\n# combine those changes -- uh oh\ngit merge branch1\n```\n\n#needs-finishing #conflicts #merging"},{"_id":"6102057c1a5d3006df000043","treeId":"6101d4901a5d3006df00001d","seq":5690343,"position":10,"parentId":"61034f1755726f6efe000035","content":"## Rebasing\n\n#needs-finishing"},{"_id":"61034c4c55726f6efe000034","treeId":"6101d4901a5d3006df00001d","seq":5690385,"position":9.5,"parentId":"6101d49f1a5d3006df00001f","content":"## Remote repositories\n\n#needs-finishing"},{"_id":"610357c055726f6efe000037","treeId":"6101d4901a5d3006df00001d","seq":5690388,"position":1,"parentId":"61034c4c55726f6efe000034","content":"### DVCS\n\n#needs-finishing"},{"_id":"6103587255726f6efe000038","treeId":"6101d4901a5d3006df00001d","seq":5690485,"position":2,"parentId":"61034c4c55726f6efe000034","content":"### Pushing, fetching and pulling\n\n- force pushing\n- fetching strategies\n\n#needs-finishing"},{"_id":"6102c30655726f6efe000031","treeId":"6101d4901a5d3006df00001d","seq":5689954,"position":15,"parentId":"6101d49f1a5d3006df00001f","content":"## Git configuration\n\n#needs-finishing\n\nGlobal, local and effective configuration."},{"_id":"610353cc55726f6efe000036","treeId":"6101d4901a5d3006df00001d","seq":5690751,"position":17,"parentId":"6101d49f1a5d3006df00001f","content":"## Getting gitty with it\n\n#needs-finishing"},{"_id":"610205961a5d3006df000044","treeId":"6101d4901a5d3006df00001d","seq":5690483,"position":1,"parentId":"610353cc55726f6efe000036","content":"### Bisecting\n\n#needs-finishing"},{"_id":"6102a96455726f6efe00002c","treeId":"6101d4901a5d3006df00001d","seq":5690482,"position":2,"parentId":"610353cc55726f6efe000036","content":"### Scripts\n\n#needs-finishing"},{"_id":"6102a9bc55726f6efe00002d","treeId":"6101d4901a5d3006df00001d","seq":5690481,"position":3,"parentId":"610353cc55726f6efe000036","content":"### Alias\n\n#needs-finishing"},{"_id":"6102a9d355726f6efe00002e","treeId":"6101d4901a5d3006df00001d","seq":5690479,"position":4,"parentId":"610353cc55726f6efe000036","content":"### Hooks\n\n#needs-finishing"},{"_id":"6103838f55726f6efe000039","treeId":"6101d4901a5d3006df00001d","seq":5690478,"position":5,"parentId":"610353cc55726f6efe000036","content":"### Chunk adding / interactive add\n\n#needs-finishing"},{"_id":"610383df55726f6efe00003a","treeId":"6101d4901a5d3006df00001d","seq":5690477,"position":6,"parentId":"610353cc55726f6efe000036","content":"### Interactive rebase\n\n#needs-finishing"},{"_id":"61047450a1ddb106e000002e","treeId":"6101d4901a5d3006df00001d","seq":5690746,"position":7,"parentId":"610353cc55726f6efe000036","content":"### Diff\n\n#needs-finishing"},{"_id":"61047515a1ddb106e000002f","treeId":"6101d4901a5d3006df00001d","seq":5690747,"position":8,"parentId":"610353cc55726f6efe000036","content":"### Archiving\n\n#needs-finishing"},{"_id":"61047925a1ddb106e0000030","treeId":"6101d4901a5d3006df00001d","seq":5690750,"position":9,"parentId":"610353cc55726f6efe000036","content":"### Describe\n\n#needs-finishing"},{"_id":"61032b3c55726f6efe000032","treeId":"6101d4901a5d3006df00001d","seq":5690752,"position":18,"parentId":"6101d49f1a5d3006df00001f","content":"## Advanced stuff\n\n- Bare repositories\n- Reference log\n- Submodules\n- subtree?\n- bundle?\n- patch?\n- rev-parse\n- update-index\n\n#needs-finishing"},{"_id":"61047a4ea1ddb106e0000031","treeId":"6101d4901a5d3006df00001d","seq":5690760,"position":19,"parentId":"6101d49f1a5d3006df00001f","content":"## References and links\n\n- https://github.com/git-tips/tips\n- https://github.com/stevemao/awesome-git-addons\n- http://www-cs-students.stanford.edu/~blynn/gitmagic/"},{"_id":"610202691a5d3006df00003b","treeId":"6101d4901a5d3006df00001d","seq":6545809,"position":5.375,"parentId":null,"content":"# Contributing\n\nI don't intend this tutorial to be very seriously taken, but I do intend it to be accurate. If you do find out inconsistencies, errors, or you want to suggest improvements, please do so. This full tutorial, its texts and videos are going to be available as a GitHub repository.\n\nIf you do want to contribute, there are several ways in which you can reach be (Twitter, Email, Facebook, LinkedIn, ...), but I suggest that the best approach would be to actually visit the repository and [open a ticket](https://github.com/AlphaGit/building-git/issues) or a [pull request](https://github.com/AlphaGit/building-git/pulls).\n\n#needs-proofreading #contributing #contact"},{"_id":"610240dcfca85a3f8b00001e","treeId":"6101d4901a5d3006df00001d","seq":6545811,"position":5.5,"parentId":null,"content":"# License\n\nThis work is shared under the [CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) license, which basically means you can do whatever you want with it as long as:\n\n* You don't commercialize it\n* You don't remove the attribution to the creators\n\nNote that these are still possibilities, but the difference is that for it to be legal, you need to request permission from me. No biggie, I'm a reasonable guy, y'know? I'll probably say yes unless you're printing copies for the mafia (and you're not giving me a good share).\n\n#needs-proofreading #license"}],"tree":{"_id":"6101d4901a5d3006df00001d","name":"Building Git: A Git Tutorial","publicUrl":"building-git-a-git-tutorial"}}