Working with version control in projects where multiple people collaborate, it is inevitable to face merge conflicts.
This is why I happen to have made a course at Metropolia University of Applied Sciences, where students are facing the following challenge after some initial git learning.
Say we have a new project without proper leadership and we need to start building the user interface, without prior consensus on the technical approach. Sounds familiar?
In the following steps and commands, I am using GIT_COMMITTER_DATE
and GIT_AUTHOR_DATE
variables to backdate the commits,
for them to seem more legit. It means that in front of every git commit
command those variables will be set and might be a source of distraction.
https://git-scm.com/docs/git-tag.html#_on_backdating_tags
The assignment in the course is returned via GitHub Classroom, by using a template repository, which is built along with the following narrative.
The repo is visible at https://github.com/Metropolia-Problematic-Git/6-mission-critical in case you are interested.
Initialize a new git repository and create the main branch with Vite and friends:
# Initialize a new git repository with "main" as the default branch
# https://git-scm.com/docs/git-init
git init --initial-branch main important-business-repo
cd important-business-repo
# Set up configuration
git config user.name "Jukka Paasonen"
git config user.email jukka.paasonen@metropolia.fi
git config user.signingkey 20601CED657892BD61
git config core.fileMode false
# Initially using Vite with React, v5.2.0 (2024-02-08)
npx --yes create-vite@v5.2.0 --template react .
# This is where I place the test files under the ".github" folder, to have them safe with the GPG signature
# Stage all files and commit them with GPG signing
git add .
GIT_COMMITTER_DATE="2024-02-22 13:35:56 +0200" GIT_AUTHOR_DATE="2024-02-22 13:35:56 +0200" \
git commit -S -m "Vite & React"
# Confirm that the first commit has a GPG signature
git log --show-signature --oneline
At some point, one person is looking to update all the dependencies by using
the npm-check-updates
tool:
git checkout -b update-some-dependencies main
ncu --filter "*react*" --target minor -u
GIT_COMMITTER_DATE="2024-03-11 19:50:07 +0200" GIT_AUTHOR_DATE="2024-03-11 19:50:07 +0200" \
git commit --author="Rick Grimes <rick@walking.dead>" -m "Update Node.js dependencies" package.json
But there was someone else doing a very similar thing too, setting up the project and then updating dependencies:
git checkout -b vite-react-typescript main
# Remove everything to avoid thinking
rm -rf * .eslintrc.cjs .gitignore
# Now use Vite with React along with Typescript, 5.4.0 (2024-07-16)
npx --yes create-vite@v5.5.0 --template react-ts .
git add .
GIT_COMMITTER_DATE="2024-07-17 08:05:18 +0200" GIT_AUTHOR_DATE="2024-07-17 08:05:18 +0200" \
git commit --author="Walter White <heisenberg@breaking.bad>" -m "Vite & React & Typescript"
#git push -u origin vite-react-typescript
Then someone else came along and wanted to use Create React App,
deleted everything and committed directly to main
, which was possible due to missing branch protection:
git checkout main
rm -rf * .eslintrc.cjs .gitignore
npx --yes create-react-app@v5.0.1 .
git add .
GIT_COMMITTER_DATE="2024-05-14 16:40:29 +0200" GIT_AUTHOR_DATE="2024-05-14 16:40:29 +0200" \
git commit --author="Cooper Howard <coop@fallout.bunker>" -m "React development early days"
Now someone realized that it’s important to have the license declared, by using one from Creative Commons.
They also use sign-off
to make their contribution fully owned by the project.
git checkout main
wget -O LICENSE https://creativecommons.org/licenses/by-sa/4.0/legalcode.txt
git add LICENSE
GIT_COMMITTER_DATE="2024-06-25 11:55:41 +0200" GIT_AUTHOR_DATE="2024-06-25 11:55:41 +0200" \
git commit --author="Dori Doreau <dori@sledge.hammer>" --signoff -m "License as CC BY-SA 4.0"
More about sign-off at cert-manager.io.
Then someone outside of the organization comes along and creates a separate branch where they revert the Create React App commit and add some features, while also signing off their contribution:
git checkout -b back-to-vite-and-use-mui main
# Check the commit hash of "React development early days", git --no-pager log --oneline
GIT_COMMITTER_DATE="2024-07-12 22:00:33 +0200" GIT_AUTHOR_DATE="2024-07-12 22:00:33 +0200" \
git revert --no-edit --signoff aeeb9d2
# Install new dependencies, https://mui.com/material-ui/getting-started/
npm install --save --package-lock-only @mui/material @emotion/react @emotion/styled
# Only committing the package.json and careful not to bring lock file
GIT_COMMITTER_DATE="2024-07-12 22:10:33 +0200" GIT_AUTHOR_DATE="2024-07-12 22:10:33 +0200" \
git commit -m "Material UI is an open-source React component library" --signoff package.json
For the sake of completeness, the package-lock.json
needs to be deleted at this point,
so it would not prevent changing branches.
rm package-lock.json
At some point, a secret token is accidentally included in the repository, most likely an easy fix when some permission handling was troublesome and it was hard to find enough information from the CI service, on how to provide secret environment variables…
# Add a secret token in a separate branch, typically along with many other things
git checkout -b fix-ci main
echo "export SECRET_TOKEN=7654gfdsuhbv765hgbv" > env.sh
git add env.sh
GIT_COMMITTER_DATE="2024-08-23 07:22:54 +0200" GIT_AUTHOR_DATE="2024-08-23 07:22:54 +0200" \
git commit --author="Leah <leah@walking.dead>" -m "Tired of complicated setup, giving up"
# Merge the branch to main, once already forgotten about the secret token
git checkout main
GIT_COMMITTER_DATE="2024-08-24 09:32:54 +0200" GIT_AUTHOR_DATE="2024-08-24 09:32:54 +0200" \
git merge --no-edit fix-ci
# Tag the merge commit to mark this as a learning victory
GIT_COMMITTER_DATE="2024-08-24 11:12:54 +0200" GIT_AUTHOR_DATE="2024-08-24 11:12:54 +0200" \
git tag victory
# Set the remote repository and push all the branches and tags
git remote add origin git@github.com:Metropolia-Problematic-Git/6-mission-critical.git
git push -u origin main
git push --all
git push --tags
Now that the problematic branch structure is in place, the assignment template is ready.
What was not listed above, are the plain Node.js test script and GitHub Actions workflow to provide feedback if the branch merging and secrets cleaning is done as specified.
How would you start solving this, given that the development should use Vite, React, and Typescript, but not Create React App?
Then also incorporate all the dependency updates, license addition, keep the sign-off, and the GPG signing in the first commit. Even the MUI library addition needs to be included.
Some commits can be dropped, and only rebasing is allowed. The end result is one linear commit history, without any tags.
A tool that can help to uncover these kinds of mistakes, is called gitleaks
,
also used in this assignment to validate the removal of that file.
Working with git has many options in addition to the command line tool, many offering almost good user experiences. A long list is provided at https://git-scm.com/downloads/guis, and the best can only be found by testing them out.
Finally I want to list these three links to get started with studying, from the providers open source git repository services: