{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreif5h4lnpvmofaioy2dpu7jbdy4lz7tutlwjmefm3p7dmirvpt25ni",
"uri": "at://did:plc:yamgjp3fq22zggtm5g7ply4n/app.bsky.feed.post/3mhveoypfi272"
},
"description": "You know the basics - branches, merges, pull requests. Now it's time to clean up after yourself. Rebasing, squashing, stashing, and the safety net that means you can't actually break anything.",
"path": "/git-mastery-for-network-engineers/",
"publishedAt": "2026-03-25T15:09:47.000Z",
"site": "https://artofinfra.com",
"tags": [
"Part 1",
"Part 2",
"here",
"Git Cheat Sheet - General CommandsWe’ve created a handy list and PDF cheat sheet of the most useful Git CLI commands covering the basics, branching, merging, rebasing, and more. Yours to keep as a quick reference for everyday tasks.Art of InfraDan Jones",
"Join Now"
],
"textContent": "In Part 1, we covered the theory. In Part 2, we got hands-on; repos, branches, merges, pull requests. If you've been following along, you've got a `network-configs` repo with switch configs, ACLs, a QoS policy, NTP config, and a `.gitignore`. You can create branches, handle merge conflicts, and open PRs.\n\nThat's great. But there's a level of Git that separates \"I know how to use it\" from \"I'm actually comfortable with it.\" That's what this post is about, and I hope by the end of this, you come away with that exact feeling.\n\nWe're covering rebasing, squashing, stashing, cherry-picking, tagging, amending commits, and the safety net that means you can try all of this without fear. These aren't _obscure_ power-user tricks, they're tools that make your day-to-day workflow cleaner, your history more readable, and your collaboration smoother.\n\nSame repo, same configs, building on what we've already done.\n\nIf you skipped the previous post, you can obtain the current state of the files and folders here.\n\n* * *\n\n## Housekeeping - Adding a README\n\nBefore we get into the advanced stuff, let's do something we probably should have done earlier. Every repo needs a README. It's the first thing anyone sees on GitHub; what this repo is, what's in it, how to use it.\n\nIn the root of your `network-configs` repo, create a `README.md`:\n\n\n # Network Configs\n\n Configuration files for the London DC core network infrastructure.\n\n ## Structure\n\n - `configs/` - Device configurations, ACLs, and policies\n - `core-sw01.cfg` - Core switch 01 (VLANs, SVIs, management)\n - `acl-vlan10.cfg` - Management VLAN access control list\n - `qos-policy.cfg` - WAN edge QoS policy (voice, video, network-control)\n - `ntp.cfg` - NTP configuration with authentication\n\n ## Branching Convention\n\n - `main` - Production-ready configs\n - `feature/*` - New features or config additions\n - `hotfix/*` - Urgent production fixes\n\nCommit and push it:\n\n\n git add README.md\n git commit -m \"Add README with repo structure and branching conventions\"\n git push\n\nDone. Nothing groundbreaking, but it's good practice and now anyone landing on this repo knows what they're looking at. If you're working in a team, this is the difference between \"What the hell is this?\" and \"Ah, got it\".\n\nGit Cheat Sheet - General CommandsWe’ve created a handy list and PDF cheat sheet of the most useful Git CLI commands covering the basics, branching, merging, rebasing, and more. Yours to keep as a quick reference for everyday tasks.Art of InfraDan Jones\n\n## Git Stash - The Quick Save You'll Actually Use\n\nWe touched on `git stash` briefly in the last post. But it deserves more attention because you'll reach for it often.\n\nHere's the scenario: you're halfway through editing the QoS policy on a feature branch when your phone goes off. There's a routing loop on the core switch, and you need to push a hotfix _immediately_. You're not ready to commit your QoS changes as theyre half done, but you can't switch branches with a _dirty_ working directory.\n\nThis is exactly what `git stash` is for.\n\n**Let's walk through it.** Start on a feature branch with some uncommitted work:\n\n\n git switch -c feature/qos-update\n\nEdit `configs/qos-policy.cfg` , say you're adjusting the video bandwidth allocation:\n\n\n class VIDEO\n bandwidth percent 35\n\nAnd you've started adding a new class, but haven't finished:\n\n\n class-map match-any SCAVENGER\n match dscp cs1\n\nNow you need to drop everything. Run the below command in the qos-update branch to stash away your changes.\n\n\n git stash\n\n\n Saved working directory and index state WIP on feature/qos-update: 349f7f9 Add NTP configuration with authentication\n\nYour working directory is clean.\n\nOpen up the `configs/qos-policy.cfg` file again, you'll notice the changes we made are no longer visible.\n\nThe half-done changes are safely stored. Switch branches, do whatever you need to do:\n\n\n git switch main\n git switch -c hotfix/core-routing\n # Fix the issue, commit, push, merge; whatever's needed\n # No requirement to do this, purely example\n\nWhen the fire's out, come back to your work:\n\n\n git switch feature/qos-update\n git stash pop\n\nYour uncommitted changes are back, exactly where you left them.\n\n### Stash Management\n\nSometimes \"fires\" overlap. You might stash multiple times before getting back to any of them. Git handles this, stashes work like a stack.\n\n\n # See what you've stashed\n git stash list\n\n\n stash@{0}: WIP on feature/qos-update: 43dec0 Add NTP config\n stash@{1}: WIP on feature/acl-cleanup: fb3123d Update management ACL\n\n # Example output. You won't have anything stashed.\n\n\n # Apply a specific stash without removing it from the list\n git stash apply stash@{1}\n\n # Apply and remove the most recent stash\n git stash pop\n\n # Drop a specific stash you no longer need\n git stash drop stash@{1}\n\n # Nuclear option - clear all stashes\n git stash clear\n\nOne thing to keep in mind: stashes are local. They don't get pushed to GitHub/ version control. If you stash work for days, you probably want a commit on a branch instead. A messy \"WIP\" commit is better than a stash you forget about.\n\n### Stashing with a Message\n\nDefault stash messages aren't really helpful. If you're going to stash multiple things, label them:\n\n\n git stash push -m \"QoS: half-done scavenger class addition\"\n\n💡\n\n`git stash push` is the explicit version of `git stash` , they do the same thing. The `-m` flag belongs to the `push` sub-command, so when you want to add a message/ label, you need to provide the full/ explicit command.\n\nNow `git stash list` actually tells you something useful:\n\n\n stash@{0}: On feature/qos-update: QoS: half-done scavenger class addition\n\nMarginally better than `WIP on feature/qos-update` , right?\n\n## Amending Commits - Fixing What You Just Did\n\nYou commit... and immediately notice you left a debug comment in the config. Or the commit message has a typo. Or you forgot to stage a file. Or.. Well.. Anything really.\n\nIf it's your most recent commit and you haven't pushed yet, `git commit --amend` is your friend.\n\n**Fix a commit message:**\n\n\n git commit --amend -m \"Add NTP configuration with MD5 authentication\"\n\nThis replaces the last commit message entirely.\n\n**Add a forgotten file:**\n\nLet's say you committed the NTP config but forgot to update the README:\n\n\n # Edit README.md to add the NTP entry\n git add README.md\n git commit --amend --no-edit\n\n`--no-edit` keeps the original commit message. The amended commit now includes the README change as if you'd staged it the first time.\n\n‼️\n\nAmending rewrites history. The old commit is replaced with a new one (different hash). If you've already pushed, you'd need to force push, which we'll talk about later. For now, the rule is simple: ****only amend commits you haven't pushed yet.****\n\n## Rebasing - The One Everyone's Afraid Of\n\nThis is a biggy. If you've heard anything about rebasing, it was probably \"don't do it\" or \"it's dangerous\". It's neither. **It's just a different way to integrate changes** , and once you understand what it's actually doing, it becomes one of the most useful tools in your arsenal.\n\nLet's start with the problem that rebase solves.\n\nthe Aoi discord community\n\nJoin our new ****Discord community**** where we discuss everything; infra, cloud, AI and much more. Come vent, discuss tech problems, or just have a place to hang out with like-minded individuals.\n\n\n Join Now\n \n\n### The Merge Commit Problem\n\nYou've been working on a feature branch for a couple of days. Meanwhile, other changes have been merged into `main`. When you merge your branch, Git creates a merge commit, and if this happens a lot, your history starts looking like a bowl of spaghetti.\n\nHere's what a merge-heavy history might look like:\n\n\n * e5f6a7b Merge branch 'feature/ntp-config'\n |\\\n | * d4e5f6a Add NTP configuration\n * | c3d4e5f Merge branch 'feature/acl-update'\n |\\ \\\n | * | b2c3d4e Update management ACL\n | |/\n * | a1b2c3d Add monitoring VLAN\n |/\n * 9f8e7d6 Initial commit\n\n**Every merge creates a junction point**. With a small team this is fine. But when you've got multiple engineers all merging feature branches daily, the history becomes hard to follow. It works, but it's noisy.\n\n### What Rebase Actually Does\n\nRebase takes your branch's commits and replays them on top of the latest `main`. Instead of creating a merge commit, it **rewrites your commits** as if you'd started your branch from the current state of `main` all along.\n\nThink of it this way: you branched off `main` on Monday to work on a new OSPF config. By Wednesday, two other changes have landed on `main`. Rebase says, \"let me take your OSPF commits, temporarily set them aside, fast-forward to where `main` is now, and then replay your commits on top.\"\n\nThe result is a straight line of history instead of a mess of merge commits.\n\n### Rebase in Action\n\nLet's set up a realistic scenario. You're adding a new OSPF configuration while a colleague pushes an update to the core switch config on `main`.\n\nCreate a new working branch:\n\n\n git switch -c feature/ospf-config\n\nCreate `configs/ospf.cfg`:\n\n\n ! OSPF Configuration - Core Router\n !\n router ospf 1\n router-id 10.0.0.1\n network 10.0.10.0 0.0.0.255 area 0\n network 10.0.20.0 0.0.0.255 area 0\n network 10.0.30.0 0.0.0.255 area 0\n passive-interface default\n no passive-interface GigabitEthernet0/0\n !\n\nAdd the file and commit:\n\n\n git add configs/ospf.cfg\n git commit -m \"Add OSPF config for core router\"\n\nLet's add a second commit, enable BFD for faster convergence:\n\n\n # Edit configs/ospf.cfg to add BFD\n router ospf 1\n bfd all-interfaces\n\nAdd the file and commit:\n\n\n git add configs/ospf.cfg\n git commit -m \"Enable BFD on OSPF interfaces\"\n\n_Meanwhile, a change lands on main._ Switch to `main` and simulate a colleague's merged change:\n\n\n git switch main\n\nEdit `configs/core-sw01.cfg` , add logging config at the end:\n\n\n !\n logging host 10.0.20.50\n logging trap informational\n logging source-interface Vlan10\n !\n\n\n git add configs/core-sw01.cfg\n git commit -m \"Add syslog configuration to core switch\"\n\nNow the setup looks like this:\n\n\n Your branch: main --- A --- B (feature/ospf-config)\n \\\n Main moved: --- C (syslog config)\n\nYour branch diverged from `main` at point A, and `main` has moved on.\n\n## Infrastructure worth reading about\n\nPractical takes on networking, cloud, and automation from someone who actually runs the gear. No fluff, no vendor pitches.\n\nSign me up\n\nEmail sent! Check your inbox to complete your signup.\n\nNo spam. Unsubscribe anytime.\n\n### The Merge Approach\n\nAs we already know, if you merged, Git would create a merge commit tying the two histories together. That works. But let's try rebase instead.\n\n### The Rebase Approach\n\n\n git switch feature/ospf-config\n git rebase main\n\n\n Successfully rebased and updated refs/heads/feature/ospf-config.\n\nWhat happened? Git took your two commits (OSPF config and BFD), temporarily removed them, moved your branch pointer to where `main` is now (including the syslog commit), and then replayed your commits on top.\n\n\n Before rebase: main --- C\n \\\n A --- B (feature/ospf-config)\n\n After rebase: main --- C --- A' --- B' (feature/ospf-config)\n\nNotice the `A'` and `B'` , these are new commits with new hashes. They contain the same changes, but they've been recreated on top of `C`. The history is now a clean straight line.\n\nWhen you merge this into `main`, it's a fast-forward, no merge commit needed:\n\n\n git switch main\n git merge feature/ospf-config\n\n\n Fast-forward\n configs/ospf.cfg | 12 ++++++++++++\n 1 file changed, 12 insertions(+)\n\nClean history. One line. Every commit visible and meaningful.\n\n### Handling Conflicts During Rebase\n\nRebase can hit conflicts, just like merge. The difference is that rebase replays your commits one at a time, so you resolve conflicts per-commit rather than all at once.\n\nIf a conflict occurs:\n\n\n CONFLICT (content): Merge conflict in configs/core-sw01.cfg\n error: could not apply a1b2c3d... Add OSPF config for core router\n\n\n # Fix the conflict in the file, then:\n git add configs/core-sw01.cfg\n git rebase --continue\n\nIf it gets messy or you want to start over:\n\n\n git rebase --abort\n\nThis puts everything back exactly how it was before you started the rebase. No damage done. This is why rebase isn't dangerous, you can always bail out.\n\n### The Golden Rule of Rebasing\n\n**Never rebase commits that have been pushed to a shared branch that others are working on.**\n\nRebase rewrites commit hashes. If someone else has based their work on commits you then rebase (and force push), their history and yours diverge in a way that's painful to fix. _Nobody wants to be that guy._\n\nThe rule in practice:\n\n * Rebasing your own local feature branch before merging? **Always fine.**\n * Rebasing a feature branch you've pushed to GitHub but nobody else is working on? **Fine, but you'll need to force push** (`git push --force-with-lease`).\n * Rebasing `main` or any shared branch? **Don't.**\n\n\n\n`--force-with-lease` is a safer version of `--force`. It checks that nobody has pushed to the remote branch since you last fetched. If they have, it refuses the push rather than overwriting their work. Always use it instead of `--force`.\n\n### When to Rebase vs. Merge\n\nBoth are tools with trade-offs:\n\n**Use rebase** when you want clean, linear history. Typically, before merging a feature branch. Your branch's commits sit neatly on top of `main` and the log reads like a chronological story.\n\n**Use merge** when you want to preserve the full picture of how things happened, who changed what, when it was merged, and where branches split and joined. This matters more in teams with strict audit or compliance requirements.\n\nA common workflow combines both: while working on your feature branch, rebase it onto `main` to pick up the latest changes and keep your history clean. This doesn't touch `main` , it only updates your branch. Then, when you're ready, open a pull request to merge your branch into `main`. You get clean history on the branch _and_ the PR gives you the review and audit trail.\n\n## Interactive Rebase - Cleaning Up Before You Share\n\nBelow, we'll create some new commits. The contents here are of no concern; we're simply practicing further Git interactions.\n\n💡\n\nIf using Mac or Linux, copy the below into your terminal to create 2 new files and add some changes/ content. The below may work with Git Bash on Windows, otherwise, you can just follow along with what we're trying to achieve.\n\n\n # Create a feature branch to work on\n git switch -c feature/ospf-dist-config\n\n # Commit 1 - start the OSPF config\n echo '! OSPF Configuration\n router ospf 1\n router-id 10.0.0.1\n network 10.0.10.0 0.0.0.255 area 0' > configs/ospf-dist.cfg\n git add configs/ospf-dist.cfg\n git commit -m \"Add OSPF baseline config\"\n\n # Commit 2 - forgot a subnet\n echo ' network 10.0.20.0 0.0.0.255 area 0' >> configs/ospf-dist.cfg\n git add configs/ospf-dist.cfg\n git commit -m \"Forgot to add area to OSPF\"\n\n # Commit 3 - add passive interfaces, still figuring it out\n echo ' passive-interface default' >> configs/ospf-dist.cfg\n git add configs/ospf-dist.cfg\n git commit -m \"Add OSPF config - WIP\"\n\n # Commit 4 - realise we need to unshut an interface\n echo ' no passive-interface GigabitEthernet0/0' >> configs/ospf-dist.cfg\n git add configs/ospf-dist.cfg\n git commit -m \"Actually fix the network statement\"\n\n # Commit 5 - add the third subnet we missed\n echo ' network 10.0.30.0 0.0.0.255 area 0' >> configs/ospf-dist.cfg\n git add configs/ospf-dist.cfg\n git commit -m \"Forgot to add area to OSPF again\"\n\n # Commit 6 - tidy up the description\n echo '!' >> configs/ospf-dist.cfg\n git add configs/ospf-dist.cfg\n git commit -m \"Fix typo in OSPF config\"\n\nSo far, we've been hacking away on a branch and our commit history looks something like this:\n\n\n git log --oneline\n\n\n 08a05d5 (HEAD -> feature/ospf-dist-config) Fix typo in OSPF config\n dc44c6e Forgot to add area to OSPF again\n b67c1e4 Actually fix the network statement\n b00c8d1 Add OSPF config - WIP\n 61df350 Forgot to add area to OSPF\n f204fec Add OSPF baseline config\n\nSix commits, three of which are basically \"oops, I messed up\". Pushing this to a PR means your reviewers have to wade through your stream of consciousness. Nobody needs to see your debugging process.\n\nInteractive rebase lets you clean this up before anyone else has to look at it.\n\n\n git rebase -i HEAD~6\n\nThis opens your editor with something like:\n\n\n pick f204fec # Add OSPF baseline config\n pick 61df350 # Forgot to add area to OSPF\n pick b00c8d1 # Add OSPF config - WIP\n pick b67c1e4 # Actually fix the network statement\n pick dc44c6e # Forgot to add area to OSPF again\n pick 08a05d5 # Fix typo in OSPF config\n\nYou can change the `pick` keyword to tell Git what to do with each commit:\n\n * `pick` - keep this commit as-is\n * `squash` (or `s`) - merge this commit into the previous one\n * `fixup` (or `f`) - like squash, but discard this commit's message\n * `reword` (or `r`) - keep the commit but change its message\n * `drop` (or `d`) - delete this commit entirely\n * `edit` (or `e`) - pause here so you can make changes\n\n\n\n### Squashing - Combining Messy Commits Into Clean Ones\n\nLet's clean up that OSPF history. We want three clean commits: one for the OSPF config (combining all the false starts), one for the ACL fix, and one final tidy-up.\n\n\n pick a1b2c3d Add OSPF baseline config\n fixup b2c3d4e Forgot to add area to OSPF\n pick c3d4e5f Fix ACL deny line\n fixup d4e5f6a Add OSPF config - WIP\n fixup e5f6a7b Actually fix the network statement\n fixup f6a7b8c Fix typo in OSPF config\n\nSave and close. Git replays the commits, combining the fixup commits into their parent. The result:\n\n\n git log --oneline\n\n\n c4c0611 (HEAD -> feature/ospf-dist-config) Add OSPF config - WIP\n c0869cd Add OSPF baseline config\n\nTwo clean and meaningful commits. Your reviewer sees what actually matters: a complete OSPF config and an ACL fix. _Not the three hours of faffing and errors it took to get there_.\n\nIf you'd used `squash` instead of `fixup`, Git would have opened your editor with all the commit messages combined, letting you write a new consolidated message. `fixup` just silently discards the message, useful when the commits are clearly just corrections.\n\nthe Aoi discord community\n\nJoin our new ****Discord community**** where we discuss everything; infra, cloud, AI and much more. Come vent, discuss tech problems, or just have a place to hang out with like-minded individuals.\n\n\n Join Now\n \n\n## Cherry-Pick - Taking Specific Commits\n\nSometimes you need one specific commit from another branch without merging the entire thing.\n\nReal-world scenario: a colleague is working on a big firewall policy overhaul on `feature/firewall-redesign`. It's weeks from being ready, but buried in that branch is a single commit that fixes a critical SNMP community string typo that's breaking your monitoring _right now_.\n\n\n # Find the commit hash\n git log --oneline feature/firewall-redesign\n\n\n h8i9j0k Update zone-based policy rules\n g7h8i9j Restructure firewall interfaces\n f6g7h8i Fix SNMP community string typo <-- this one\n e5f6g7h Begin firewall policy redesign\n\n\n git switch main\n git cherry-pick f6g7h8i\n\nThat single commit, the SNMP fix, is now applied to `main`. The rest of the firewall work stays on its branch.\n\n_A few things to note about cherry-pick:_\n\nIt creates a new commit with a new hash (similar to rebase). The change is the same, but Git doesn't track any relationship between the cherry-picked commit and the original. If the commit you're picking touches the same lines as something on your current branch, you'll get a conflict to resolve, same process as any other conflict (you know the drill by now).\n\n## Tags - Marking Points in Time\n\nBranches move. Every new commit advances the branch pointer. Sometimes you need to mark a specific point in history that doesn't move, a known-good baseline, a config version that passed audit, or the state of things before a major change window.\n\nThat's what tags are for.\n\n**Create a tag:**\n\n\n # Lightweight tag - just a pointer\n git tag v1.0\n\n # Annotated tag - includes a message, author, date (preferred for anything meaningful)\n git tag -a v1.0 -m \"Baseline configs - pre-OSPF deployment\"\n\n**Push tags to GitHub:**\n\n\n # Push a specific tag\n git push origin v1.0\n\n # Push all tags\n git push --tags\n\n**List and use tags:**\n\n\n # See all tags\n git tag\n\n # See tag details\n git show v1.0\n\n # Check out a tagged version (detached HEAD - read only, don't commit here)\n git checkout v1.0\n\nFor network engineering, tags are a natural fit. Think about your change windows: before deploying a new routing protocol across the network, tag the current state. If it goes sideways, you've got an instant, named reference point to compare against or roll back to.\n\n\n git tag -a pre-ospf-deployment -m \"Baseline before OSPF rollout - change CHG001234\"\n\nThat ties your Git history directly to your change management process.\n\n## Reflog - The Safety Net\n\nHere's the thing that should make you worry less about all of this: **Git almost never permanently deletes anything.** Even if you rebase, amend, reset, or delete a branch, the old commits still exist in Git's reflog for at least 30 days.\n\n\n git reflog\n\n\n a1b2c3d (HEAD -> main) HEAD@{0}: merge feature/ospf-config: Fast-forward\n c3d4e5f HEAD@{1}: checkout: moving from feature/ospf-config to main\n b2c3d4e HEAD@{2}: rebase (finish): refs/heads/feature/ospf-config\n 9f8e7d6 HEAD@{3}: rebase (start): checkout main\n d4e5f6a HEAD@{4}: commit: Enable BFD on OSPF interfaces\n e5f6a7b HEAD@{5}: commit: Add OSPF config for core router\n\nThe reflog records every action that changed where `HEAD` points. If you rebase and hate the result:\n\n\n # Find the commit hash from before the rebase\n git reflog\n\n # Reset back to that point\n git reset --hard HEAD@{4}\n\nEverything is restored. The rebase is undone.\n\nThis is why \"I broke everything with rebase\" is almost always recoverable. The reflog is your time machine. The only way to actually lose work is to run `git reflog expire` or wait 30+ days _and_ run garbage collection.\n\nA couple of caveats:\n\n * reflog is local. It doesn't get pushed to GitHub.\n * It only tracks actions on your machine, so it won't help if you overwrote a colleague's work on the remote.\n\n\n\n## Infrastructure worth reading about\n\nPractical takes on networking, cloud, and automation from someone who actually runs the gear. No fluff, no vendor pitches.\n\nSign me up\n\nEmail sent! Check your inbox to complete your signup.\n\nNo spam. Unsubscribe anytime.\n\n## Useful Aliases - Because Life's Too Short\n\nIf you're running these commands regularly, give your fingers a break. Git supports aliases for frequently used commands:\n\n\n git config --global alias.st status\n git config --global alias.co checkout\n git config --global alias.sw switch\n git config --global alias.br branch\n git config --global alias.lg \"log --oneline --graph --decorate --all\"\n git config --global alias.last \"log -1 HEAD\"\n git config --global alias.unstage \"reset HEAD --\"\n\nNow instead of:\n\n\n git log --oneline --graph --decorate --all\n\nYou just type:\n\n\n git lg\n\nThe `lg` alias is great, it gives you a visual branch graph in a compact format. You'll use it a lot when working with multiple branches.\n\n* * *\n\nYou can now safely delete the Git repo we've been working on throughout this part of the series, play around further with the skills you've learned so far, or keep it for future reference. Totally your call!\n\nFuture articles in the series will involve real configurations being pushed to devices.\n\n* * *\n\n## What's Next\n\nYou now have a Git workflow that goes beyond the basics. You can keep a clean history, handle interruptions without losing work, selectively pick commits, and mark important milestones. More importantly, you know that the `reflog` has your back when you're experimenting.\n\nThe Git portion of this series is now done. You've gone from \"What's version control?\" to a workflow that most developers would consider solid. That's no minor thing!\n\nNext, we're shifting gears entirely.\n\nWe'll look at **APIs and network programmability** , why the CLI isn't enough when you want to automate at scale, how REST APIs, NETCONF, and gRPC give you programmatic access to your network devices, and why this ties directly into the version-controlled workflow we've built here. The configs are in Git.\n\nThe next question is: \"how do you push them to devices without SSH and copy-paste?\"\n\n* * *\n\n_Part 3: APIs & Network Programmability — coming soon._",
"title": "Git Mastery - Rewriting History and Advanced Workflows for Network Engineers",
"updatedAt": "2026-03-25T15:16:41.874Z"
}