The #1 guiding principle for answering these questions that I've found is:
Start with "Why?".

Why are you writing any code at all?

Are you writing code to test a hypothesis and present the results of testing
that hypothesis to other people? If so, state that hypothesis explicitly,
build the minimum needed to test that hypothesis, and have a clear & concise
document (Dropbox Paper, README.md, etc) explaining how the code tests the
hypothesis.

Are you writing code to build a product that you plan to maintain for 5-10
years as you add features and support a larger user base? That implies that in
5 years, you are going to have some new junior engineer join the team who will
need to figure out how to navigate this codebase and modify it. They will have
a job to do and the UI they have to accomplish this job will consist of:

- The codebase itself (including any tests)

- The commit history of the codebase

- Any diagrams or READMEs that were written alongside the codebase

- The issue tracker

- The other members of the team and their memories and communication habits.

Engineering practices and team habits matter because they mean that your more
junior engineers are able to much more quickly and confidently do projects to
solve evolving business needs as much or writing as many bugs. Think of both your codebase and your project management tools as a UI whose users are the engineering team trying to accomplish business needs. This talk is close to the mindset I'm trying to convey: https://skillsmatter.com/skillscasts/10124-dylan-beattie-the...

Speaking personally, I find that automated testing is extremely useful for
moving quickly because it makes it easier for me to break a task down into
concrete pieces and to stay motivated by having constant positive feedback.
The cost of testing is that it takes a while to set up and is especially
difficult if you are not experienced in the toolset you are using. If you
don't have a good testing toolchain in place, then writing and running tests
is really painful and gets in the way of development

For this reason, it is tremendously useful to have testing infrastructure and
practices set up early on in a project by someone who is experienced with the
particular framework/language you are using. It is very difficult to introduce
tests after-the-fact.

The branching and code review process that I've found most useful is:

```

$ git checkout -b my-feature

# Write some code.

$ git add -p

$ git commit -m "do some small thing"

$ git status

$ git checkout file/that/has/leftover/edits/I/dont/want

# Repeat.

$ git rebase -i HEAD^^^^^

# re-order commits, edit commit messages, and squash some
commits into

# larger logical blocks.

$ git checkout master

$ git pull origin master

$ git checkout my-feature

$ git rebase master

# It now looks like my-feature was developed off the tip of
master

# And I've resolved any potential merge conficts.

$ git push origin my-feature -f

```
And then make a pull request to merge to master and tag someone to review.
CircleCI runs the full automated test suite on the PR. I've only run the few
tests that I've modified because they're the ones that relate to my PR.
It doesn't make sense to require passing tests for every commit because then
you can't write PRs where the tests fail. You might want to do this so you can
show someone a Work In Progress and ask for advice. It might make sense to run
a linter like rubocop on each commit, but only if each of the linter rules
is agreed-on by the team (just make a PR for it and have people +1 or -1).

If I need to make changes to the PR after pushing, I do so and then I rebase
on top of master again and `git push -f` the branch. Once tests pass and
someone +1s it, I'll merge to master and start on the next chunk of work in
the project. Note that on Github, if you tag someone for a review, and they
make a comment, you need to tag them again for your PR to show up in their
list of PRs-to-review.

Keep your work tightly in-sync with master. If there is a feature
that I don't want to go live, I use a feature flag to turn it off rather than
keeping it out-of-sync with master. Merging large changes that have gotten far
out of sync is hell.

For project management, try to be as lightweight as you can. We use a 1-page
markdown doc of "Here are good questions to ask to make sure you've understood
the scope of the problem and have talked to relevant stakeholders." and we
break the project up into trello cards that roughly correspond to PRs.