Boot.dev Blog
Symlinks in Linux: How to Create and Use Them
by Boot.dev Team - Programming course authors and video producers
A symlink lets one file live at two paths: the real one, and a lightweight pointer that forwards to it. It's one of those Linux features you can ignore for years, then suddenly use every day once you've seen what it's for (dotfiles, versioned tool installs, and log directories, to name a few). Here's what symlinks are, how to create them with ln -s, and how they differ from copies.
Linux Shell Configuration: .bashrc, .zshrc, and Beyond
by Boot.dev Team - Programming course authors and video producers
Your shell runs a configuration file every single time it starts, and once you know how to edit it, you can customize almost everything about your command line experience. In this post you'll learn how shell configuration files like .bashrc and .zshrc work, how to make PATH changes permanent, and how to get a proper local setup: WSL 2 for Windows users, and a terminal emulator you'll actually enjoy.
Linux Package Managers: apt, brew, and How They Work
by Boot.dev Team - Programming course authors and video producers
A package manager is a software tool that helps you install other software. As a developer, you'll frequently use package managers to get access to the software you need to get your work done. In this post we'll cover the two most popular package managers you'll run into on Linux and macOS — apt and brew — how they work under the hood, and how to use them to install real tools like Neovim and VS Code.
Shell vs Terminal: What's Actually the Difference?
by Boot.dev Team - Programming course authors and video producers
The terms "shell," "terminal," "command line," and "CLI" are used interchangeably all the time, and honestly, that's usually fine. But they are not the same thing, and understanding the difference makes everything else about working in a text-based environment easier. Here we'll cover what a terminal actually is, what a shell does, why developers prefer typing commands over clicking buttons, and some shell basics like variables and history.
How to Kill a Process in Linux: top, kill, and Signals
by Boot.dev Team - Programming course authors and video producers
Every program running on your machine is a process, and sooner or later one of them will misbehave: a script stuck in an infinite loop, a command chewing through all your RAM, a program that just won't respond. In this post you'll learn how to see what's running with top, how to interrupt a program with [[Ctrl]]+[[C]], and how to escalate to the kill command (and the dreaded kill -9) when a process refuses to die.
Linux Filesystem Commands Every Beginner Should Know
by Boot.dev Team - Programming course authors and video producers
All the data on your computer is organized into files and directories, and as a developer you'll spend a lot of time creating, moving, reading, and deleting them from the command line. This guide covers the core Linux filesystem commands: pwd, ls, and cd for navigation, cat, head, tail, and less for reading files, touch, mkdir, mv, rm, and cp for managing them, and grep and find for searching.
Stdin, Stdout, and Stderr: Linux I/O Streams Explained
by Boot.dev Team - Programming course authors and video producers
Programs running in a shell have a standard way of talking to you and to each other: three data streams called stdin, stdout, and stderr. Combine those streams with flags, positional arguments, and exit codes, and you can chain simple commands together into incredibly powerful automations using redirection and pipes.
The PATH Environment Variable in Linux, Explained
by Boot.dev Team - Programming course authors and video producers
Sooner or later, every developer installs a program, types its name into the terminal, and gets hit with an error: command not found. Usually, the culprit is the PATH environment variable: the list of directories your shell searches when you try to run a command. To understand your PATH (and how to fix it when it breaks), it helps to understand how programs run on Linux in the first place. So that's where we'll start: compiled vs interpreted programs, executables, shebangs, and environment variables. Then we'll dig into the PATH itself and how to change it.
Man Pages in Linux: How to Actually Read Them
by Boot.dev Team - Programming course authors and video producers
Every command line tool you'll ever use ships with a built-in instruction manual, and most developers never read it. The man command puts the full documentation for ls, grep, cp, and hundreds of other programs one keystroke away, right in your terminal. Here's how man pages work, and how to actually find what you're looking for inside one.
Linux File Permissions Explained: chmod, chown, and sudo
by Boot.dev Team - Programming course authors and video producers
In a Unix-like operating system, permissions control who can do what to which files and directories. If you've ever run a script only to be slapped with permission denied, or typed sudo because the internet told you to, this is the missing context. In this article you'll learn how the rwx permission model works, how to change permissions with chmod, how to change ownership with chown, and when you should (and shouldn't) reach for sudo.
Git Cherry-Pick: Copy One Commit to Another Branch
by ThePrimeagen - Ex-Netflix engineer, NeoVim ricer, and Git rebaser
There comes a time in every developer's life when you want to yoink a commit from a branch, but you don't want to merge or rebase because you don't want all the commits. git cherry-pick solves this: it takes a single commit from anywhere in your repo and applies it to your current branch, no full merge required.
Git Worktrees: Work on Multiple Branches at Once
by ThePrimeagen - Ex-Netflix engineer, NeoVim ricer, and Git rebaser
Git normally only lets you have one branch checked out at a time. Want to review a coworker's PR while you're halfway through a refactor? You're either stashing, committing WIP garbage, or cloning the whole repo again. Git worktrees fix this: they let you check out multiple branches at once, each in its own directory, all connected to the same repository.
Git Merge Conflicts: What They Are and How to Fix Them
by ThePrimeagen - Ex-Netflix engineer, NeoVim ricer, and Git rebaser
Working with Git is a dream when all of the developers on a project are committing changes to different lines of code. Things get a little hairy when changes to the same lines are made at the same time. That's when Git throws up its hands, declares a merge conflict, and makes you sort it out. In this post you'll learn what merge conflicts actually are, how to read those nasty <<<<<<< conflict markers, and how to resolve conflicts both by hand and with Git's built-in tools.
Git Squash Commits: How to Combine Commits Into One
by ThePrimeagen - Ex-Netflix engineer, NeoVim ricer, and Git rebaser
Every dev team will have different standards and opinions on how to use Git. Some teams require all pull requests to contain a single commit, while others prefer to see a series of small, focused commits. If you join a team that prefers a single commit, you will need to know how to "squash" your commits together. To be fair, even if you don't need a single commit, squashing is useful to keep your commit history clean.
Git Tags: How to Version and Release Your Code Properly
by ThePrimeagen - Ex-Netflix engineer, NeoVim ricer, and Git rebaser
Branches move. Every time you commit, your branch pointer slides forward to the newest commit. But sometimes you want the opposite: a name that's permanently stuck to one specific commit, usually because that commit is a release you'll want to find again later. That's what git tags are for. In this post you'll learn how to create, list, and push tags, and how semantic versioning gives your tags names that actually mean something.
Git Stash: Save Uncommitted Changes and Get Them Back
by ThePrimeagen - Ex-Netflix engineer, NeoVim ricer, and Git rebaser
Your working directory is full of half-finished changes, and suddenly you need to switch to something else right now. You're not ready to commit (the code doesn't even work yet) but you can't afford to lose it either. That's exactly what git stash is for: it tucks your uncommitted changes into a safe place, gives you a clean working directory, and lets you pull everything back out when you're ready.
Git Rebase Conflicts: How to Resolve Them Without Fear
by ThePrimeagen - Ex-Netflix engineer, NeoVim ricer, and Git rebaser
Full disclosure: a lot of git rebase's bad rep comes from conflicts! Fear not. It's nothing you can't handle with just a smidge of practice.
Git Reflog: Recover Deleted Branches and Lost Commits
by ThePrimeagen - Ex-Netflix engineer, NeoVim ricer, and Git rebaser
Deleted a branch with commits on it? Botched a rebase? Reset something you shouldn't have? The git reflog command is Git's last resort: it records every move your references make, which means "lost" commits are almost never actually lost. In this article you'll learn how to read the reflog, and then use it to recover a deleted branch, first the hard way with plumbing commands, then the easy way with a single merge.
Git Revert: Undo Commits Without Rewriting History
by ThePrimeagen - Ex-Netflix engineer, NeoVim ricer, and Git rebaser
Sometimes you need to undo a commit that's already on a shared branch. You could reach for git reset, but resetting rewrites history, and rewriting shared history is a great way to ruin your coworkers' day. git revert undoes a commit the polite way: by adding a new commit that reverses the old one. Nothing gets deleted, history stays intact, and nobody wants you dead.
Git Fork: How to Fork a Repo and Open Your First PR
by ThePrimeagen - Ex-Netflix engineer, NeoVim ricer, and Git rebaser
A fork is a copy of a repository. Forking a repository allows you to freely experiment with changes without affecting the original project. It's also the standard way to contribute to open source: you don't need write access to someone's repo to fork it, change it, and offer your changes back.
Closures in Python: How They Capture State
by Boot.dev Team - Programming course authors and video producers
A [closure]() is a function that references variables from outside its own function body. The function definition and its environment are bundled together into a single entity, so it keeps track of some values from the place where it was defined, no matter where it's executed later on.
Higher-Order Functions in Python
by Boot.dev Team - Programming course authors and video producers
In Python, functions are just values, like strings, integers, or objects. A programming language "supports first-class functions" when functions are treated like any other variable. That means functions can be passed as arguments to other functions, can be returned by other functions, and can be assigned to variables. Functions that accept other functions as arguments or return functions are called higher-order functions, and they power built-ins like map(), filter(), and reduce().
Pure Functions in Python: A Complete Beginner Guide
by Boot.dev Team - Programming course authors and video producers
If you take nothing else away from this article, please take this: pure functions are fantastic. A pure function has exactly two properties: it always returns the same value given the same arguments (it's deterministic), and running it causes no [side effects](). In short: pure functions don't do anything with anything that exists outside of their scope.
Currying in Python: Transform Multi-Arg Functions
by Boot.dev Team - Programming course authors and video producers
Function currying is a specific kind of function transformation, where we translate a single function that accepts multiple arguments into multiple functions that each accept a single argument.
What Is Functional Programming in Python? A Complete Guide
by Boot.dev Team - Programming course authors and video producers
Functional programming is a style of programming where we compose functions instead of mutating state (updating the values of variables). While Python is best known for object-oriented programming, it also fully supports functional concepts like first-class functions, immutability, and pure functions. Learning to think functionally is one of the fastest ways to write cleaner, more maintainable code, no matter which language you end up working in.
