~$ skillshelf
← OverTheWire Bandit

Bandit 31 → 32: the file git kept pretending to add

banditlinuxgit

Five git levels in a row, and this is the one that flips direction. Every level before it handed me a repository to dig through; this one wants something put into it. Create a file, commit it, push it — and the push came back telling me there was nothing to send.

the goal

There is a git repository at ssh://bandit31-git@localhost/home/bandit31-git/repo via the port 2220. The password for the user bandit31-git is the same as for the user bandit31. From your local machine (not the OverTheWire machine!), clone the repository and find the password for the next level. This needs git installed locally on your machine.

Word for word the last four again. The actual task isn’t on the level page at all — it’s in the repo, in README.md:

File name: key.txt
Content: 'May I come in?'
Branch: master

the approach

Clone from my own machine, since localhost in that URL still means whichever machine runs the command — the 27 → 28 lesson, still applying five levels later:

git clone ssh://bandit31-git@bandit.labs.overthewire.org:2220/home/bandit31-git/repo

Then the file, spelled exactly the way the README asks for it:

echo 'May I come in?' > key.txt
git add key.txt
git commit

the identity error that hid the real one

git refused the commit — not over the file, over me. It wanted a name and an email before it would write anything:

git config --global user.name bandit31
git config --global user.email bandit31@overthewire.org

Real failure, real fix, and also the reason the next thing took a while: I’d just watched a commit get refused and then repaired, so when the push did nothing I had no reason to look at the file. The first problem made the second one look like it had already been solved.

git push origin master
Everything up-to-date

Which is a strange thing to be told about a file that is definitely not up there.

nothing to commit

git status
nothing to commit, working tree clean

Now two commands agreeing there was nothing to do, about a file I could see in ls. “Working tree clean” does not mean “your file is committed” — it means nothing git is tracking differs from HEAD, and a file git has been told to ignore is not something it’s tracking.

The trap is one line, and it shipped with the repo:

.gitignore

*.txt

key.txt matches. So git add key.txt put nothing in the index, git commit had nothing to commit, and git push had nothing to push. Four commands doing exactly what they were told, and every one of them honest — the mistake happened before the first of them ran.

force it past

git add -f key.txt
git commit -m "Add key.txt"
git push origin master

-f is the whole fix: it tells add to stage the file even though an ignore rule covers it. With the file actually inside a commit the push had something to carry, and the password came back with it — redacted here as <password>.

the takeaway

git add -f forces a file past .gitignore. That’s the brick — a one-flag answer to a problem that gives you no error to work from.

What made it cost that much is the shape of the failure. Nothing errored. add, commit, push and status were all correct and all useless, because an ignore rule had removed the file from the conversation before any of them started. An empty index gives you four commands’ worth of true, unhelpful answers. A dead end that announces itself is easy; this one agrees with you.

Two smaller ones:

“Everything up-to-date” is a statement about commits, not about intent. It means the remote branch has everything the local branch has. It says nothing whatsoever about the file sitting in the directory you’re standing in.

A repo you cloned arrives with its rules attached. .gitignore is a file in the repository, written by whoever built it — and here it was written to swallow *.txt on a level whose entire task is to commit key.txt. Reading it costs one command, and it’s the one worth running before you trust anything downstream.