You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
12 KiB
12 KiB
title | marp | paginate | theme |
---|---|---|---|
Project management 2. Git continued | true | true | buutti |
Project management 2. Git continued
Branches
- A Git repository can have multiple branches
- By default, a Git repository has only one branch
- named usually
main
ormaster
- named usually
- Using multiple branches makes it possible to work on new features step by step in their own feature branches
- Meanwhile, the
main
branch is kept clean and in a working state - Only when the feature is completed, the branch is merged into the
main
branch!
- Meanwhile, the
Active branch
- Even though your local repository can have multiple branches, only one of them is active at a given time
git status
tells you firsthand which branch you are on:On branch main
git branch
& git checkout
- You can create a new branch with
git branch <branchname>
- The new branch is not empty: it contains a copy of the code of the branch you executed this command in
- Note:
git branch <branchname>
does not make the branch active! - To make the branch active, a.k.a "move" to the branch:
git checkout <branchname>
.- For example, to move back to the main branch, use
git checkout main
Local vs. remote branches
git branch <branchname>
only creates a local branch- When you try to push changes from a new local branch for the first time, Git nags you that a matching remote branch doesn't yet exist
- Git tells you how to create the remote branch:
git push --set-upstream origin <branchname>
- Afterwards,
git push
pushes the changes to the matching remote branch
- Git tells you how to create the remote branch:
Extra branch commands
- Handy command:
git checkout -b <branchname>
- It's a shorthand for
git branch <branchname>
+git checkout <branchname>
- It's a shorthand for
- Get a list of local branches with
git branch
- ...and all branches (incl. the remote ones) with
git branch -a
- ...and all branches (incl. the remote ones) with
- Delete a local branch with
git branch -d <branchname>
- Remote branch can be deleted in the GitLab/etc website
- ...or with
git push origin -d <branchname>
- ...or with
- Note: If deleted remote branches still show up in
git branch -a
, you can use the commandgit remote prune origin
to remove them from the list.
- Remote branch can be deleted in the GitLab/etc website
git merge
- When a feature is done (and all the broken things fixed), you want to apply, i.e., merge your changes from the feature branch to the
main
branch
- First, checkout the
main
branch withgit checkout main
- Then, do a
git pull
so you have the newest version of themain
branch- (Someone else might have done changes to it while you were working on your feature!)
- Then, merge your local feature branch to your local main branch with
git merge <featurebranch>
- It applies changes from
<featurebranch>
to the current active branch - This is where conflicts might happen (more about them later)
- It applies changes from
- Then, push your changes to remote with
git push
Merging with a pull/merge request
- The aforementioned procedure isn't what we usually do, though!
main
branch should be protected so we can't merge our new code there directly- Instead, we do the inverse.
- First, checkout the
main
branch withgit checkout main
- Then, do a
git pull
so you have the newest version of themain
branch - Then, checkout back to the feature branch.
- Merge your local
main
branch to your localfeaturebranch
withgit merge main
- Then, create a merge request on GitLab (it's pull request on GitHub—they're the same thing, just named from different points of view.)
Simplifying merging further
- Pro tip: If you're working on your feature branch, you can merge changes from the
main
branch without changing branches altogether.
- Update your local main branch with
git fetch origin main:main
- Merge your local
main
branch to your localfeaturebranch
withgit merge main
- Then, create a merge request/pull request
- Much easier this way!
- But what is the merge request, anyway?
Merge request/pull request
- Merge/pull request is a formal process for merging your remote feature branch straight to the remote
main
branch - This adds a layer of protection to the
main
branch: no direct merging to themain
branch! - Additionally, a code review can happen at this stage:
- If a code maintainer thinks your merge request needs some modifications, you can make changes to the feature branch accordingly
- A merge request is branch-specific, so when you push your changes to your feature branch, the merge request is automatically updated as well.
- If this procedure is followed strictly, no bad code should get into the main branch!
GitHub pull request UI
- UI of a new pull request (Pull requests > New pull request) can be confusing...
- base is the branch you're merging, compare is the branch you're merging into.
Exercise 1. Pushing onwards
Continue the exercise from Git Basics or create a new repository for these exercises.
- Create a new branch (with a name
new-feature
, for instance) in your local repository. - Checkout the branch, make some changes to
GitTest.md
there, and push the changes to GitLab. - Then, merge the changes from your
new-feature
branch to themain
branch by using a)git merge
from command line b) a merge request in GitLab
GitLens
- To make the Git workflow easier, install the GitLens extension to VS code
- It helps in managing conflicts, comparing branches or commits
- Install it from the Extensions panel (access with CTRL+SHIFT+X)
- Adds many new views to the source control tab
Conflicts
- Sometimes two people have made changes in the same lines of code!
- This leads to a conflict.
- Let's assume we're trying to merge changes from
featurebranch
tomain
. - If a conflict happens, the merge does not conclude automatically.
- Instead, we need to fix all the conflicts by hand and then conclude the merge with some commands.
- Conflicting lines of code are framed by some
<<<< garbage ==== symbols >>>>
we don't yet understand - Before we can conclude the merge, we need to get rid of the garbage.
Garbage explained
<<<<<<< HEAD:Player.cs
if (Input.anyKey) {
return true;
}
=======
if (Input.anyKey)
return true;
>>>>>>> featureBranch:Player.cs
- Current change is between
<<<<<<<
and=======
- old code that was already in
main
- old code that was already in
- Incoming change is between
>>>>>>>
and=======
- new code coming from
featurebranch
- new code coming from
- Use your text editor to choose which (or some combination of both) you want to preserve
VS Code tools
- VS Code gives us tools to make conflict resolution a relatively quick process
- Choose your preference:
- Accept Current Change (old code is preserved, new code is removed)
- Accept Incoming Change (new code is preserved, old code is removed)
- Accept Both Changes (both are preserved)
After resolving the conflict
- After resolving all conflicting files, use
git add <filename>
to add them to the commit - Then use
git commit
to apply changes (without a message! no-m
)- Close the automatically opened
COMMITMSG
file. - This finishes the merge.
- Close the automatically opened
- Then just
git push
to apply changes in the remote repository - Note: If VS code is not configured properly as the Git's text editor, and you encounter an error, run
git config core.editor code --wait
Example Git workflow with branches
Exercise 2. Fixing conflicts
Continue in the Exercise 1 repository.
- Create a new branch in your local repository, but do not checkout it just yet.
- On the
main
branch, make some changes toGitTest.md
, and add & commit. - Then, checkout the new feature branch.
- Make some other changes to GitTest.md to the same line as before, add & commit.
- Then, merge the changes from the
main
branch to your feature branch by usinggit merge
- Fix the ensuing conflicts, add & commit & push.
Undoing
- Git doesn't have a general "undo" command
- If you make a mistake, it is very case-specific what you need to do to fix it
- See undo options here
- Also, ohshitgit.com
git log
& git checkout <hashcode>
-
Use
git log
to see the commit history- Or
git log --oneline
for a more concise version - Press Q to quit the log view.
- The newest changes are seen on top
- On the left side of the commit message you see the hashcode of the commit
- Use
git checkout <hashcode>
to "time travel" into the commit
- Or
-
Note: If you have GitLens, check the Commits view in the Source control tab to see the commit history.
Reverting one file to a previous state
- Sometimes you want to revert just one file to its previous state
- You can use
git checkout <commit-hash> -- <filename>
to time travel just that file to how it was in that commit - For this, you of course need to figure out the commit hash you want to return to
- Find that out in one of the following methods:
git log --oneline
- VS Code: Source control > File history
- Check commits from GitHub/GitLab
Exercise 3. Branching team effort
Work as a group for this assignment. Continue Exercise 2 from Git basics.
- Every group member: create your own individual branch from the
main
branch - Then, make some changes to the
GitTest.md
file.- Do not tell other group members what you're going to change! :D
- Add new files as well, at least one file per group member.
- Then, merge the changes back to the
main
branch. Fix ensuing conflicts, if any appear.
Reading
Very extra: git rebase
git merge
creates a new commit for the merge process- Sometimes that's undesirable, so an alternative is to use
git rebase
- Unlike merge, rebase applies changes from the rebased branch one commit at a time
- Whenever there's a conflict:
- After fixing the conflict, add the conflicting file with
git add <filename>
- Then continue the rebase process with
git rebase --continue
- If you want to disregard a conflicting commit, use
git rebase --skip
- If you get cold feet, you can cancel the rebase with
git rebase --abort
Very extra: Interactive git rebase -i
git rebase
also has a hidden interactive mode used withgit rebase -i
- This is a true swiss army knife of a Git tool for rewriting Git history
- It can:
- Squash commits into one
- Cherry-pick only certain commits
- Reword commit messages
- And more!
- See Hackernoon: Beginner’s Guide to Interactive Rebasing
Very very extra: Git submodules
- To add external code to your project from someone else's repository, Git has a neat system called submodules
- To add a submodule to your project, use
git submodule add <submodule-url> <folder>
- To remove a submodule, use
git rm <path-to-submodule>
- If you clone a project with submodules, you need to run
git submodule update --init --recursive
once. - Note: If you don't want submodules to appear in the Source control tab of VS Code, go to settings and disable the Git: Detect Submodules setting.