DEV Community

Cover image for How to get somebody fired using Git
Mauro Accorinti
Mauro Accorinti

Posted on • Edited on

How to get somebody fired using Git

This is Billy.

Stick figure with a smile and a red tie
He is a trainee developer working for an important company.

Unfortunately for the company, today Billy has woken up and chosen violence.

This is because he finds learning Git very troublesome, boring and convoluted.

Branches, commits, checkouts, HEADs, features, staging, oh my!

It was just too much for him.

But then Billy had the absolutely best worst idea.

"What if I learn git by first learning what NOT to do, but then doing it anyway!"

This would accomplish three things:

  1. He would learn git's most common tools by giving himself fun little challenges that would normally be prohibited.
  2. If he learned what not to do, he could then later focus on what he should do.
  3. Learning this way satisfies his chaotic evil tendencies.

This was sounding more and more like a good idea to Billy. This would definitely make him a better developer.

There was just one problem though...

Git is a version control system used by developers to manage source code for software.

Whenever something is changed, added or even deleted by somebody, Git registers who did what.

If you wanted to do very bad things in, let's say, a repository owned by the company you work at, somebody could always trace it back to you.

And that would DEFINETELY get you fired.

So that's why Billy stole Trent's computer.

Billy the stick figure holding up a realistic laptop that reads

Trent is a big dumb-dumb who left his computer on and unprotected when he went to the bathroom.

He also ate the last slice of pizza at last month's after party without asking first.

With Trent's computer, Billy now has access to the same repositories, but under Trent's login credentials.

And so now Billy can learn Git by first learning everything he shouldn't do, like:

1. Pushing code to somebody else's branch with --force

Let's say the current git ecosystem looks like this:

Git Diagram of main and the co-worker's feature branch.

Billy is currently checked out on an earlier version of another co-worker's branch.

This can happen if 2 people are checked out on the same branch, but one of them starts pushing changes to the remote.

This means that Billy is behind on the branch. If he wanted to get the latest changes of the branch he currently is on, he would write into the terminal git pull

Fun fact:
Git pull is actually the combination of 2 other git commands.

  • git fetch origin (which fetches the latest changes of remote WITHOUT checking out or merging it)
  • git merge origin/<branch name> (which does merge your local changes to the remote. Since normally you wouldn't have local files to merge, git does what's called a "fast-forward" and you end up with the latest changes)

Billy wonders what would happen if he tried pushing on this person's branch, even if he's behind on the latest changes.

Normally if he tried to git push some code, the attempt would fail with an error - Asking him to pull the latest changes first.

(This is a safety net that's built into git to avoid having work be lost. You can't push unless you pull first!)

But Billy can avoid this if he did a git push --force command.

git push --force is usually a big nono for developers. It's a command that forcibly overwrites the git history and lets you push your local changes despite it possibly deleting other people's work on the same branch.

Billy has never used it before and is a curious boy, so he did what any curious person would do.

  1. He created a new file with special text inside:
    echo "Trent was here" > Trent.txt

  2. He committed his very important changes to the branch
    git add Trent.txt
    git commit -m "Trent committed this"

Which makes git look like this:

Git flow diagram showing how his co-workers changes disappear and Billy's new code overwrites it

  1. He finishes by force-pushing his new changes to the branch git push --force

After a few seconds...

Poof!

Billy's very important changes are now in Git!

And at the same time, all of his co-worker's work completely disappears!

If only Billy had used git push --force-with-lease!

--force-with-lease is the safer version of the --force command. It would have prevented Billy from ever overwriting his coworker's work on the remote.

Oh well! What's done is done. And in the end, having fun is what matters.

Billy wonders how long he has before that co-worker notices.

He also wonders if there's something that's even worst he can do. Maybe... he can do something similar in Production?

A light bulb goes off in Billy's head! What if he did a:

2. Hard Reset on the production branch

Git reset is a command that, similar to what Billy did to his co-worker, undo's the changes that have been created in a branch to a previous commit.

Unlike the git push --force command he learned earlier, there's nothing to push. It just rewrites the git history by (usually) uncommitting everything done up to a certain commit.

There's 3 modes to the git reset command.

  1. git reset --soft which moves HEAD (Head being the commit you're currently checked out on) back to the specified commit, while also undoing all the changes made. All those changes go back to staged and allow you to commit again.

  2. git reset --mixed does the same as git reset --soft, but leaves all the changes you've made unstaged. This is also the default mode for the git reset command. So if you write git reset, that would be the same as doing git reset --mixed.

  3. git reset --hard is diabolical. Instead of undoing the changes and leaving them in staged / unstaged... it just discards them.

Poof

All those changes disappear when you hard reset to an old commit.

So if Billy were to say... hard reset to a commit that's from, oh I don't know, 6 months ago, that would be very bad for the company.

Billy smiles as he opens up the terminal.

Remembering what the git ecosystem looks like:

Git branch showing the 6 month old commit and the latest one

Billy happily starts:

  1. Typing into the terminal git checkout main which positions him on the latest commit of that branch.

  2. Uses a git visual tool to find a commit from the main branch that's 6 months old.

  3. Types git reset --hard <commit hash> to erase all the changes in the main branch from the last 6 months locally.

  4. Finishes off by using our good friend git push --force to permanently leave his local destructive changes in the remote.

After a few seconds...

Poof!

Billy successfully made some company executives very very angry!

But wait a minute...

It's weird that Billy was able to do that, wasn't it? After all...

Permissions are usually set in repositories so that nobody can push to the production branch directly.

This prevents accidental pushing or rewriting of git history that affects the website directly.

That's why something called a "Pull Request" (or a PR) exists.

A pull request is a proposal to merge a set of changes from one branch into another.

And normally, other tech savvy developers first have to accept your changes before you can merge anyway.

But what happens if those permissions are never set?

Well, seems like anybody like Billy can come and erase everybody's hard work from the last 2 quarters in a second.

He calculates he has maybe 10... no, 15 minutes before his changes to main impact in production.

So Billy has to act fast. He has time for maybe one more chaotic evil thing before somebody named Trent gets in trouble.

What to do...

OH, Billy knows! He should:

3. Expose the project's secrets and push it to production!

Billy can easily do this by modifying the .gitignore file.

.gitignore is a special type of file located in your project's directory. As the name implies, it specifies which files Git should ignore and avoid letting you stage.

This is super helpful when you have particular files you never want to upload to your repository in the first place.

One of those files you normally want to avoid uploading are your .env files.

.env files tend to be used in projects to hold environment variables you would use throughout your solution.

They feature key/value pairs with information you really really don't want to upload. Things such as API keys, database URIs, AUTH secrets and more.

But Billy doesn't believe in keeping secrets to oneself.

He is the hero of his story and must let the people know!

So if we assume our .gitignore files looks like this:

# Javascript node_modules
node_modules/

# API keys
.env
Enter fullscreen mode Exit fullscreen mode

Then all Billy has to do is:

  1. Locate the .gitignore file

  2. Use his favorite IDE or terminal text editor to remove the .env line from the file and save it. (Which makes the file now look like this)

    # Javascript node_modules
    node_modules/
    
    # API keys are gone from ignore oops
    
  3. Add the now changed .gitignore file to staged. Billy does this by typing git add .gitignore into the terminal

  4. Oh wait! Don't forget - Since Git now isn't ignoring the .env file, Billy has to add that too! git add .env is typed into the terminal as well.

  5. Time for committing! Billy does this with this line:

    git commit -m "FREEEEEEDOOOOOMMM!!!! #TrentWasHere"

  6. Final step! Time to push to the main branch. And since again, for some reason there isn't any permissions set that would stop Billy, he can write git push --force into the terminal.

After a few seconds...

Poof!

"Liberté, égalité, fraternité" whispers Billy with glee! Right as he leaves Trent's computer where it belongs.

Good thing too, as he just heard the sound of a toilet flush from a room away.

Billy runs back to his desk, making it just in time before anybody notices.

Phew

Seems like Trent finally came back from his bathroom break and sat down at his desk.

But right before he could even open his laptop, Trent's phone started ringing.

Ring ring, ring ring

Billy waited in anticipation as he saw Trent slowly pick up his phone.

"Hello?"

"TRENT. OFFICE. NOW."

Billy could hear the yelling from Trent's phone from 5 desk's away.

"WOAH what happened boss?"

...

"I didn't do anything lik-"

...

"What do you something happened to production?

...

"I'm on my way"

And as Trent quickly runs to the office, probably for the screaming of his lifetime.

Billy sits back, relaxes and can finally say:

"I'm a better developer today".

Billy the stick figure is smiling


This was the dumbest article I have ever written.

If you like my sense of humor then I think you'll like my newsletter "Exceptional Frontend" - the most entertaining front-end newsletter on the web.

It's for any devs out there that want a front-end centered newsletter that tries to be different from everybody else. Big focus was put into making it unique and most importantly — FUN!

While also at the same time helping devs become exceptional at what they do.

You can sign up here.

Top comments (93)

Collapse
 
pshaddel profile image
Poorshad Shaddel

Poor Trent should have been familiar with git reflog :) Nice article!

Collapse
 
mauroaccorinti profile image
Mauro Accorinti

Thank you so much!

Git reflog would have definetely saved the day here

Collapse
 
ethanwillingham profile image
Ethan Willingham

This article is genius, sucked me in with entertainment and actually got me to read something and become informed, thankyou!

Collapse
 
mauroaccorinti profile image
Mauro Accorinti

Let's goooo, glad it helped and you enjoyed it!

Collapse
 
kquiggins profile image
Kenneth Quiggins

Adding lessons in with a sense of humor, I love it. 😎

Collapse
 
mauroaccorinti profile image
Mauro Accorinti

Thanks Kenneth! The world needs fun git tutorials hahaha

Collapse
 
kquiggins profile image
Kenneth Quiggins

It most definitely does my friend 🙏

Collapse
 
thawkin3 profile image
Tyler Hawkins

That was great, thanks for the laugh! Well written.

Collapse
 
mauroaccorinti profile image
Mauro Accorinti

Thanks for the kind comment!

Collapse
 
wiktorwandachowicz profile image
Wiktor Wandachowicz

That's why everybody and their dog should not use plain --force because it may be destructive.

Instead always use git push --force-with-lease (!)

Found this little gem while watching "So You Think You Know Git - FOSDEM 2024" on YouTube, around 17:42. There is even part 2 of this video 😊

See:

Collapse
 
sin_noariaaisin_2849 profile image
Sin No Aria (AI Sin)

Out of curiosity, is there a reason why they aren't flipped? Like why it wasn't designed with force being force with lease by default and the current force being a force without lease command?

Collapse
 
mauroaccorinti profile image
Mauro Accorinti

So after a few google searches, I honestly couldn't find the answer! So I just went into the Git repository and went down to a tag made 20 years ago.

Here's the git push documentation from that moment:
github.com/git/git/blob/v0.99/Docu...

My guess is git push was made first and then somewhere down the line the option to push with lease was added later.

Collapse
 
mauroaccorinti profile image
Mauro Accorinti

Thank you for mentioning it! The resources you posted are also excellent so it adds a lot.

Thanks to you and another commenter, I decided to at least mention it in the article.

Collapse
 
jankapunkt profile image
Jan Küster

If a previous commit is stable and you messed up things a lot (not necessary due to wrong git usage) then git reset --hard <commit hash> may be exactly what you need

Collapse
 
mauroaccorinti profile image
Mauro Accorinti

Oh absolutely! There's a use case and everything for git reset. Especially when you know what you're doing. Git is super powerful for that reason.

Git push - -force also has its uses. It's necessary for doing a clean rebase or when you want to cleanly amend a commit.

It's all about responsible use.

This article was about irresponsible use 😅

Collapse
 
jankapunkt profile image
Jan Küster

The article is great! Just wanted to leave this one to make people curious. I also love converting on these kind of articles, finding gems I never heard/read before 👍

Collapse
 
spo0q profile image
spO0q • Edited

Congrats for this article. Pretty fun. In real conditions, sign your commits + protect main branches against forced push.

Pull requests can also mitigate those issues (which is mentioned in the post)

Collapse
 
mikec711g profile image
Michael Casile

Creative way to provide some serious DON'Ts and why

Collapse
 
mauroaccorinti profile image
Mauro Accorinti

Thank you for the kindness!

Collapse
 
joao9aulo profile image
João Paulo Martins Silva

The best way to learn, doing wrong things.

Collapse
 
mauroaccorinti profile image
Mauro Accorinti

There's no better way to learn 😄

Collapse
 
segudev profile image
Thomas Segura • Edited

Great article.
For reference, when a .env file is pushed to public GitHub, it is 54% likely to expose a secret (and it happens a lot..)
source: The State of Secrets Sprawl 2024

Collapse
 
mauroaccorinti profile image
Mauro Accorinti

Awesome stat! Really liked the phrase:
“Compromised credentials are a gift that keeps on giving
(your stuff away)”

Some comments may only be visible to logged-in visitors. Sign in to view all comments.