<lidata-marpit-fragment="1">A Git repository can have multiple <em><strong>branches</strong></em></li>
<lidata-marpit-fragment="2">By default, a Git repository has only one branch
<ul>
<lidata-marpit-fragment="3">named either <code>master</code> or <code>main</code></li>
<lidata-marpit-fragment="3">named usually <code>main</code> or <code>master</code></li>
</ul>
</li>
<lidata-marpit-fragment="4">Using multiple branches makes it possible to work on new features step by step in their own <em><strong>feature branches</strong></em>
<ul>
<lidata-marpit-fragment="5">Meanwhile, the <code>master</code> branch is kept clean and in a working state</li>
<lidata-marpit-fragment="6">Only when the feature is completed, the branch is merged into the <code>master</code> branch!</li>
<lidata-marpit-fragment="5">Meanwhile, the <code>main</code> branch is kept clean and in a working state</li>
<lidata-marpit-fragment="6">Only when the feature is completed, the branch is merged into the <code>main</code> branch!</li>
<lidata-marpit-fragment="1">Even though your local repository can have multiple branches, only one of them is <em>active</em> at a given time</li>
<lidata-marpit-fragment="2"><code>git status</code> tells you firsthand which branch you are on: <code>On branch master</code></li>
<lidata-marpit-fragment="2"><code>git status</code> tells you firsthand which branch you are on:<preis="marp-pre"data-auto-scaling="downscale-only"><code>On branch main
<h3id="local-vs-remote-branches">Local vs. remote branches</h3>
<ul>
<lidata-marpit-fragment="1"><code>git branch <branchName></code> only creates a local branch</li>
<lidata-marpit-fragment="2">When you try to push changes from a new local branch, Git nags you that a matching remote branch doesn't yet exist
<lidata-marpit-fragment="1"><code>git branch <branchname></code> only creates a <em><strong>local</strong></em> branch</li>
<lidata-marpit-fragment="2">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
<ul>
<lidata-marpit-fragment="3">Git tells you how to create the remote branch:
<lidata-marpit-fragment="2">It's a shorthand for <code>git branch <branchName></code> + <code>git checkout <branchName></code></li>
<lidata-marpit-fragment="2">It's a shorthand for <code>git branch <branchname></code> + <code>git checkout <branchname></code></li>
</ul>
</li>
<lidata-marpit-fragment="3">Get a list of local branches with <code>git branch</code>
@ -86,102 +89,116 @@
<lidata-marpit-fragment="4">...and all branches (incl. the remote ones) with <code>git branch -a</code></li>
</ul>
</li>
<lidata-marpit-fragment="5">Delete a local branch with <code>git branch -d <branchName></code>
<lidata-marpit-fragment="5">Delete a local branch with <code>git branch -d <branchname></code>
<ul>
<lidata-marpit-fragment="6">Remote branch can be deleted in the GitHub/etc website</li>
<lidata-marpit-fragment="7">...or with <code>git push origin -d <branchName></code></li>
<lidata-marpit-fragment="6">Remote branch can be deleted in the GitLab/etc website
<ul>
<lidata-marpit-fragment="7">...or with <code>git push origin -d <branchname></code></li>
</ul>
</li>
<lidata-marpit-fragment="8"><em><strong>Note:</strong></em> If deleted remote branches still show up in <code>git branch -a</code>, you can use the command <code>git remote prune origin</code> to remove them from the list.</li>
<lidata-marpit-fragment="1">So you've been working on a feature branch. What next?</li>
<lidata-marpit-fragment="2">When the feature is done (and all the broken things fixed), you want to apply your changes back to <code>master</code></li>
<lidata-marpit-fragment="3">For this, we use <code>git merge <branchToMerge></code>
<ul>
<lidata-marpit-fragment="4">It applies changes from <code><branchToMerge></code> to the <em><strong>current active branch</strong></em></li>
</ul>
</li>
<lidata-marpit-fragment="5"><code>master</code> branch is usually (and should be) protected, so we can't merge our new code to <code>master</code> directly</li>
<lidata-marpit-fragment="6">Instead, we do the <em>inverse</em>.</li>
<lidata-marpit-fragment="1">When a feature is done (and all the broken things fixed), you want to apply, i.e., <em><strong>merge</strong></em> your changes from the feature branch to the <code>main</code> branch</li>
<lidata-marpit-fragment="3">Pull changes from GitHub/etc</li>
<lidata-marpit-fragment="4">Checkout the feature branch</li>
<lidata-marpit-fragment="5">Merge the contents of <code>master</code> to <code>featureBranch</code> with <code>git merge master</code></li>
<lidata-marpit-fragment="4">(Someone else might have done changes to it while you were working on your feature!)</li>
</ul>
<olstart="2">
<lidata-marpit-fragment="6">Then, create a <em><strong>pull request</strong></em> on GitHub/etc (In GitLab, it's called <em><strong>merge request</strong></em>!)</li>
</ol>
</li>
<lidata-marpit-fragment="5">Then, merge your local feature branch to your local main branch with<br/>
<code>git merge <featurebranch></code>
<ul>
<lidata-marpit-fragment="7">This creates a formal process for merging your <em>remote</em> feature branch to remote <code>master</code></li>
<lidata-marpit-fragment="8">This adds a layer of protection to the <code>master</code> branch: no direct merging!</li>
<lidata-marpit-fragment="6">It applies changes from <code><featurebranch></code> to the <em><strong>current active branch</strong></em></li>
<lidata-marpit-fragment="7">This is where <em><strong>conflicts</strong></em> might happen (more about them <ahref="#conflicts">later</a>)</li>
</ul>
</li>
<lidata-marpit-fragment="8">Then, push your changes to remote with <code>git push</code></li>
<h3 id="merging-with-a-pullmerge-request">Merging with a pull/merge request</h3>
<ul>
<lidata-marpit-fragment="1">UI of a new pull request (<em>Pull requests > New pull request</em>) can be confusing...
<lidata-marpit-fragment="1">The aforementioned procedure isn't what we usually do, though!</li>
<lidata-marpit-fragment="2"><code>main</code> branch should be <em><strong>protected</strong></em> so we can't merge our new code there directly
<ul>
<lidata-marpit-fragment="2"><em>base</em> is the branch you're merging, <em>compare</em> is the branch you're merging into!</li>
<lidata-marpit-fragment="3">Instead, we do the <em>inverse</em>.</li>
</ul>
</li>
</ul>
<ol>
<lidata-marpit-fragment="4">First, checkout the <code>main</code> branch with <code>git checkout main</code></li>
<lidata-marpit-fragment="5">Then, do a <code>git pull</code> so you have the newest version of the <code>main</code> branch</li>
<lidata-marpit-fragment="6">Then, <em><strong>checkout back to the feature branch</strong></em>.</li>
<lidata-marpit-fragment="7">Merge your local <code>main</code> branch to your local <code>featurebranch</code> with<br/>
<code>git merge main</code></li>
<lidata-marpit-fragment="8">Then, create a <em><strong>merge request</strong></em> on GitLab (it's <em><strong>pull request</strong></em> on GitHub—they're the same thing, just named from different points of view.)</li>
<lidata-marpit-fragment="1"><em><strong>Pro tip:</strong></em> If you're working on your feature branch, you can merge changes from the <code>main</code> branch without changing branches altogether.</li>
</ul>
<ol>
<lidata-marpit-fragment="1">Pull remote changes to your local <code>master</code>.
<lidata-marpit-fragment="2">Update your local main branch with <code>git fetch origin main:main</code></li>
<lidata-marpit-fragment="3">Merge your local <code>main</code> branch to your local <code>featurebranch</code> with<br/>
<code>git merge main</code></li>
<lidata-marpit-fragment="4">Then, create a merge request/pull request</li>
</ol>
<ul>
<lidata-marpit-fragment="5">Much easier this way!
<ul>
<lidata-marpit-fragment="2"><em><strong>Pro tip:</strong></em> If you're on your feature branch, you can do this quickly without changing branches with<br/>
<code>git fetch origin master:master</code></li>
<lidata-marpit-fragment="6">But what is the merge request, anyway?</li>
</ul>
</li>
<lidata-marpit-fragment="3">Merge changes from <code>master</code> to your local feature branch.</li>
<lidata-marpit-fragment="4">Fix the ensuing <em><strong>conflicts</strong></em> (see <ahref="#3-conflicts">next section</a>)</li>
<lidata-marpit-fragment="5">Push your new local branch to GitHub/etc</li>
<lidata-marpit-fragment="3">Someone else might have done changes to it while you were working on your feature!</li>
<lidata-marpit-fragment="1">Merge/pull request is a formal process for merging your <em>remote</em> feature branch straight to the remote <code>main</code> branch</li>
<lidata-marpit-fragment="2">This adds a layer of protection to the <code>main</code> branch: no direct merging to the <code>main</code> branch!</li>
<lidata-marpit-fragment="3">Additionally, a <em><strong>code review</strong></em> can happen at this stage:
<ul>
<lidata-marpit-fragment="4">If a code maintainer thinks your merge request needs some modifications, you can make changes to the feature branch accordingly</li>
<lidata-marpit-fragment="5">A merge request is branch-specific, so when you push your changes to your feature branch, the merge request is automatically updated as well.</li>
<lidata-marpit-fragment="6">If this procedure is followed strictly, no bad code should get into the main branch!</li>
</ul>
</li>
<lidata-marpit-fragment="4">Then, merge <code><featureBranch></code> to <code>master</code> with <code>git merge <featureBranch></code>
<lidata-marpit-fragment="1">Sometimes two people have made changes in the same lines of code!
<ul>
<lidata-marpit-fragment="2">This leads to a conflict.</li>
<lidata-marpit-fragment="2">This leads to a <em><strong>conflict</strong></em>.</li>
</ul>
</li>
<lidata-marpit-fragment="3">Let's assume we're trying to merge changes from featureBranch to master.</li>
<lidata-marpit-fragment="4">If a conflict happens, the merge does not conclude automatically. Instead, we need to <em><strong>fix all the conflicts</strong></em> by hand and then <em><strong>conclude the merge</strong></em> with some commands.</li>
<lidata-marpit-fragment="5">Conflicting lines of code are framed by some <code><<<<<<< garbage ======= symbols >>>>>>></code> we don't yet understand</li>
<lidata-marpit-fragment="6">Before we can conclude the merge, we need to get rid of the garbage.</li>
<lidata-marpit-fragment="3">Let's assume we're trying to merge changes from <code>featurebranch</code> to <code>main</code>.</li>
<lidata-marpit-fragment="4">If a conflict happens, the merge does not conclude automatically.</li>
<lidata-marpit-fragment="5">Instead, we need to <em><strong>fix all the conflicts</strong></em> by hand and then <em><strong>conclude the merge</strong></em> with some commands.</li>
<lidata-marpit-fragment="6">Conflicting lines of code are framed by some <code><<<< garbage ==== symbols >>>></code><br/>
we don't yet understand</li>
<lidata-marpit-fragment="7">Before we can conclude the merge, we need to get rid of the garbage.</li>
<lidata-marpit-fragment="1"><em><strong>Current change</strong></em> is between <code><<<<<<<</code> and <code>=======</code>: old code in <code>master</code></li>
<lidata-marpit-fragment="2"><em><strong>Incoming change</strong></em> is between <code>>>>>>>></code> and <code>=======</code>: new code from <code>featureBranch</code></li>
<lidata-marpit-fragment="3">Use your text editor to choose which (or some combination of both) you want to preserve</li>
<lidata-marpit-fragment="1"><em><strong>Current change</strong></em> is between <code><<<<<<<</code> and <code>=======</code>
<ul>
<lidata-marpit-fragment="2">old code that was already in <code>main</code></li>
</ul>
</li>
<lidata-marpit-fragment="3"><em><strong>Incoming change</strong></em> is between <code>>>>>>>></code> and <code>=======</code>
<ul>
<lidata-marpit-fragment="4">new code coming from <code>featurebranch</code></li>
</ul>
</li>
<lidata-marpit-fragment="5">Use your text editor to choose which (or some combination of both) you want to preserve</li>
<lidata-marpit-fragment="1">VS Code gives us tools to make conflict resolution a quick process</li>
<lidata-marpit-fragment="2">Click which lines of code you want to preserve:
<lidata-marpit-fragment="1">VS Code gives us tools to make conflict resolution a relatively quick process</li>
<lidata-marpit-fragment="2">Choose your preference:
<ul>
<lidata-marpit-fragment="3"><em><strong>Accept Current Change</strong></em> (old code is preserved, new code removed)</li>
<lidata-marpit-fragment="4"><em><strong>Accept Incoming Change</strong></em> (new code is preserved, old code removed)</li>
<lidata-marpit-fragment="5"><em><strong>Accept Both Changes</strong></em> (both are preserved)</li>
<lidata-marpit-fragment="3"><em><strong>Accept Current Change</strong></em><br/>
(old code is preserved,<br/>
new code is removed)</li>
<lidata-marpit-fragment="4"><em><strong>Accept Incoming Change</strong></em> (new code is preserved,<br/>
old code is removed)</li>
<lidata-marpit-fragment="5"><em><strong>Accept Both Changes</strong></em><br/>
(both are preserved)</li>
</ul>
</li>
</ul>
</section>
</foreignObject><foreignObjectwidth="1280"height="720"data-marpit-advanced-background="pseudo"><sectiondata-marpit-fragments="5"data-paginate="true"data-class="invert"data-heading-divider="3"data-theme="79cyd3oru1j29cg66ofi9uvfluhymakxwh6huu59m5" lang="en-US"class="invert"data-marpit-pagination="17" style=""data-marpit-pagination-total="27"data-marpit-advanced-background="pseudo"data-marpit-advanced-background-split="right"></section></foreignObject></svg><svgdata-marpit-svg=""viewBox="0 0 1280 720"><foreignObjectwidth="1280"height="720"><sectionid="18" data-marpit-fragments="4" data-paginate="true"data-class="invert"data-footer="If VS code is not configured properly as Git's text editor, and you encounter an error, run `git config core.editor code --wait`"data-heading-divider="3"data-theme="79cyd3oru1j29cg66ofi9uvfluhymakxwh6huu59m5" lang="en-US"class="invert"data-marpit-pagination="18" style="--paginate:true;--class:invert;--heading-divider:3;--theme:79cyd3oru1j29cg66ofi9uvfluhymakxwh6huu59m5;" data-marpit-pagination-total="27">
<h2id="after-resolving-the-conflict">After resolving the conflict</h2>
<h3id="after-resolving-the-conflict">After resolving the conflict</h3>
<ul>
<lidata-marpit-fragment="1">After resolving conflicting files, use <code>git add <filename></code> to add them to the commit</li>
<lidata-marpit-fragment="1">After resolving all conflicting files, use <code>git add <filename></code> to add them to the commit</li>
<lidata-marpit-fragment="2">Then use <code>git commit</code> to apply changes (without a message! no <code>-m</code>)
<ul>
<lidata-marpit-fragment="3">Close the automatically opened <code>COMMITMSG</code> file. This should finish the merge.</li>
<lidata-marpit-fragment="3">Close the automatically opened <code>COMMITMSG</code> file.</li>
<lidata-marpit-fragment="4">This finishes the merge.</li>
</ul>
</li>
<lidata-marpit-fragment="4">Then just <code>git push</code> to apply changes in the remote repository</li>
<lidata-marpit-fragment="5">Then just <code>git push</code> to apply changes in the remote repository</li>
<lidata-marpit-fragment="6"><em><strong>Note:</strong></em> If VS code is not configured properly as the Git's text editor, and you encounter an error, run <code>git config core.editor code --wait</code></li>
</ul>
<footer>If VS code is not configured properly as Git's text editor, and you encounter an error, run <code>git config core.editor code --wait</code></footer>
<lidata-marpit-fragment="1">Create a new branch in your local repository, but do not checkout it just yet.</li>
<lidata-marpit-fragment="2">First, we simulate your teammate's changes by making changes to the <code>master</code> branch directly: On the <code>master</code> branch, make some changes to <code>GitTest.md</code>, and <strong>add & commit</strong>.</li>
<lidata-marpit-fragment="2">On the <code>main</code> branch, make some changes to <code>GitTest.md</code>, and <strong>add & commit</strong>.</li>
<lidata-marpit-fragment="3">Then, checkout the new feature branch.</li>
<lidata-marpit-fragment="4">Then, make some other changes to GitTest.md to the same line as before, <strong>add & commit</strong>.</li>
<lidata-marpit-fragment="5">Then, merge the changes from the <code>master</code> branch to your feature branch by using <code>git merge</code></li>
<lidata-marpit-fragment="4">Make some <em><strong>other</strong></em> changes to GitTest.md to the same line as before, <strong>add & commit</strong>.</li>
<lidata-marpit-fragment="5">Then, merge the changes from the <code>main</code> branch to your feature branch by using <code>git merge</code></li>
<lidata-marpit-fragment="6">Fix the ensuing conflicts, add & commit & push.</li>
<lidata-marpit-fragment="7">Now you can create a pull request to merge your changes to the master branch.</li>
<h3 id="reverting-one-file-to-a-previous-state">Reverting one file to a previous state</h3>
<ul>
<lidata-marpit-fragment="1">Sometimes you want to revert just one file to its previous state</li>
<lidata-marpit-fragment="2">For that, you need to figure out the commit hash of the state you want to return to</li>
<lidata-marpit-fragment="3">Find that out in one of the following methods:
<lidata-marpit-fragment="2">You can use <code>git checkout <commit-hash> -- <filename></code> to time travel just that file to how it was in that commit</li>
<lidata-marpit-fragment="3">For this, you of course need to figure out the commit hash you want to return to</li>
<lidata-marpit-fragment="4">Find that out in one of the following methods:
<h2id="collaboration-in-unity">Collaboration in Unity</h2>
<ul>
<lidata-marpit-fragment="1"><em><strong>The zeroth rule:</strong></em> Make sure that everyone on team uses the same Unity and package versions.</li>
<lidata-marpit-fragment="2"><em><strong>The first rule:</strong></em> Don't ever work on the same thing simultaneously.</li>
<lidata-marpit-fragment="3"><em><strong>The second rule:</strong></em> When you do break rule #1, make necessary changes in communication so you won't break it again.</li>
<lidata-marpit-fragment="4">Be sure to communicate about <em><strong>scene ownership</strong></em>
<ul>
<lidata-marpit-fragment="5">Scenes are not code files, so you can't easily merge changes if two people have worked on them</li>
<lidata-marpit-fragment="6">Thus, the <em><strong>Scene Owner</strong></em> will be the only person on the team who should be working on a certain scene</li>
<lidata-marpit-fragment="7">If a scene needs GameObject contributions from others, they can create prefabs that the Scene Owners then add to their scene</li>
<h2id="exercise-3-branching-team-effort">Exercise 3. Branching team effort</h2>
<p>Work as a group for this assignment. Continue Exercise 2 from <ahref="1-git-basics">Git basics</a>.</p>
<ol>
<lidata-marpit-fragment="1">Every group member: create your own individual branch from the <code>main</code> branch</li>
<lidata-marpit-fragment="2">Then, make some changes to the <code>GitTest.md</code> file.
<ul>
<lidata-marpit-fragment="1">Work as a group for this assignment.</li>
<lidata-marpit-fragment="2">Continue Exercise 2 from <ahref="1-git-basics">Git basics</a>.</li>
<lidata-marpit-fragment="3">Every group member creates an individual branch from the master, and makes some changes to the <code>GitTest.md</code> file.</li>
<lidata-marpit-fragment="4">Add new files as well, at least one per group member.</li>
<lidata-marpit-fragment="5">Do not tell other group members what you're going to change! :D</li>
<lidata-marpit-fragment="6">Then, merge the changes back to the master branch. Fix ensuing conflicts, if any appear.</li>
<lidata-marpit-fragment="3">Do not tell other group members what you're going to change! :D</li>
</ul>
</li>
<lidata-marpit-fragment="4">Add new files as well, at least one file per group member.</li>
<lidata-marpit-fragment="5">Then, merge the changes back to the <code>main</code> branch. Fix ensuing conflicts, if any appear.</li>
<h2id="very-extra-interactive-git-rebase--i">Very extra: Interactive <code>git rebase -i</code></h2>
<ul>
<lidata-marpit-fragment="1"><code>git rebase</code> also has a hidden <em><strong>interactive</strong></em> mode used with <code>git rebase -i</code></li>
<lidata-marpit-fragment="2">This is a true swiss army knife of a Git tool for rewriting Git history</li>
<lidata-marpit-fragment="3">It can:
<ul>
<lidata-marpit-fragment="9"><em><strong>Note:</strong></em> A good link for <ahref="https://borbware.github.io/unity-basics-course/project-management/2-git-continued-slides.html">understanding rebase</a></li>
<lidata-marpit-fragment="4">Squash commits into one</li>
<lidata-marpit-fragment="5">Cherry-pick only certain commits</li>
* A Git repository can have multiple ***branches***
* By default, a Git repository has only one branch
* named either `master` or `main`
* named usually `main` or `master`
* Using multiple branches makes it possible to work on new features step by step in their own ***feature branches***
* Meanwhile, the `master` branch is kept clean and in a working state
* Only when the feature is completed, the branch is merged into the `master` branch!
* 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!

### 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 master`
* `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>`
* 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!
* ***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 master use `git checkout master`
* `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, Git nags you that a matching remote branch doesn't yet exist
* `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 <newBranch>`
* `git push --set-upstream origin <branchname>`
* Afterwards, `git push` pushes the changes to the matching remote branch
### Extra branch commands
<!-- _class: "extra invert" -->
* Handy command: `git checkout -b <branchName>`
* It's a shorthand for `git branch <branchName>` + `git checkout <branchName>`
* Handy command: `git checkout -b <branchname>`
* It's a shorthand for `git branch <branchname>` + `git checkout <branchname>`
* Get a list of local branches with `git branch`
* ...and all branches (incl. the remote ones) with `git branch -a`
* Delete a local branch with `git branch -d <branchName>`
* Remote branch can be deleted in the GitHub/etc website
* ...or with `git push origin -d <branchName>`
* 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>`
* ***Note:*** If deleted remote branches still show up in `git branch -a`, you can use the command `git remote prune origin` to remove them from the list.
## `git merge`
* So you've been working on a feature branch. What next?
* When the feature is done (and all the broken things fixed), you want to apply your changes back to `master`
* For this, we use `git merge <branchToMerge>`
* It applies changes from `<branchToMerge>` to the ***current active branch***
* `master` branch is usually (and should be) protected, so we can't merge our new code to `master` directly
* Instead, we do the *inverse*.
* 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
1) First, checkout the `main` branch with `git checkout main`
2) Then, do a `git pull` so you have the newest version of the `main` branch
* (Someone else might have done changes to it while you were working on your feature!)
3) 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](#conflicts))
4) Then, push your changes to remote with `git push`
## Merging with a pull request
### Merging with a pull/merge request
1) Make sure you have the newest version of the `master` branch:
* Checkout `master` branch
* Pull changes from GitHub/etc
* Checkout the feature branch
* Merge the contents of `master` to `featureBranch` with `git merge master`
2) Then, create a ***pull request*** on GitHub/etc (In GitLab, it's called ***merge request***!)
* This creates a formal process for merging your *remote* feature branch to remote `master`
* This adds a layer of protection to the `master` branch: no direct merging!
* 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*.
1) First, checkout the `main` branch with `git checkout main`
2) Then, do a `git pull` so you have the newest version of the `main` branch
3) Then, ***checkout back to the feature branch***.
4) Merge your local `main` branch to your local `featurebranch` with
`git merge main`
5) 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.
1) Update your local main branch with ```git fetch origin main:main```
2) Merge your local `main` branch to your local `featurebranch` with
`git merge main`
3) Then, create a merge request/pull request
* 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!
* Much easier this way!
* But what is the merge request, anyway?
### If automatic merge fails...
### Merge request/pull request
1) Pull remote changes to your local `master`.
* ***Pro tip:*** If you're on your feature branch, you can do this quickly without changing branches with
```git fetch origin master:master```
2) Merge changes from `master` to your local feature branch.
3) Fix the ensuing ***conflicts*** (see [next section](#3-conflicts))
4) Push your new local branch to GitHub/etc
* 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 the `main` 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!
## Extra: Merging without a pull request
<!-- _class: "extra invert" -->
### GitHub pull request UI

1) First, checkout the `master` branch with `git checkout master`
2) Then, do a `git pull` so you have the newest version of the `master` branch
* Someone else might have done changes to it while you were working on your feature!
3) Then, merge `<featureBranch>` to `master` with `git merge <featureBranch>`
* Fix conflicts
* 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
<!--_class: "exercise invert" -->
Continue the exercise from [Git Basics](1-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 GitHub.
* Then, merge the changes from your `new-feature` branch to `master` branch by using
a) pull request in GitHub
b) `git merge` from command line
1) Create a new branch (with a name `new-feature`, for instance) in your local repository.
2) Checkout the branch, make some changes to `GitTest.md` there, and push the changes to GitLab.
3) Then, merge the changes from your `new-feature` branch to the `main` 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:
* Adds many new views to the source control tab
<divclass='columns12'markdown='1'>
<divmarkdown='1'>
* For example:
* Commits
* Repositories
* File History
* Line History
* Branches
* Remotes
* etc...
# 3. Conflicts
</div>
<divmarkdown='1'>

</div>
</div>
## 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 to master.
* 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
* This leads to a ***conflict***.
* Let's assume we're trying to merge changes from `featurebranch` to `main`.
* 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.
### Said garbage
### Garbage explained
```c#
<<<<<<<HEAD:Player.cs
@ -145,40 +166,51 @@ Continue the exercise from [Git Basics](1-git-basics) or create a new repository
return true;
>>>>>>> featureBranch:Player.cs
```
* ***Current change*** is between `<<<<<<<` and `=======`: old code in `master`
* ***Incoming change*** is between `>>>>>>>` and `=======`: new code from `featureBranch`
* ***Current change*** is between `<<<<<<<` and `=======`
* old code that was already in `main`
* ***Incoming change*** is between `>>>>>>>` and `=======`
* new code coming from `featurebranch`
* 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 quick process
* Click which lines of code you want to preserve:
* ***Accept Current Change*** (old code is preserved, new code removed)
* ***Accept Incoming Change*** (new code is preserved, old code removed)
* ***Accept Both Changes*** (both are preserved)
* 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 conflicting files, use `git add <filename>` to add them to the commit
### 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 should finish the merge.
* Close the automatically opened `COMMITMSG` file.
* This finishes the merge.
* 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
<!-- _footer: "If VS code is not configured properly as Git's text editor, and you encounter an error, run `git config core.editor code --wait`" -->

## Exercise 2. Fixing conflicts
<!--_class: "exercise invert" -->
* Create a new branch in your local repository, but do not checkout it just yet.
* First, we simulate your teammate's changes by making changes to the `master` branch directly: On the `master` branch, make some changes to `GitTest.md`, and **add & commit**.
* Then, checkout the new feature branch.
* Then, make some other changes to GitTest.md to the same line as before, **add & commit**.
* Then, merge the changes from the `master` branch to your feature branch by using `git merge`
* Fix the ensuing conflicts, add & commit & push.
* Now you can create a pull request to merge your changes to the master branch.
Continue in the Exercise 1 repository.
## Git workflow 3: Undoing
1) Create a new branch in your local repository, but do not checkout it just yet.
2) On the `main` branch, make some changes to `GitTest.md`, and **add & commit**.
3) Then, checkout the new feature branch.
4) Make some ***other*** changes to GitTest.md to the same line as before, **add & commit**.
5) Then, merge the changes from the `main` branch to your feature branch by using `git merge`
6) 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
@ -195,37 +227,26 @@ Continue the exercise from [Git Basics](1-git-basics) or create a new repository
* Use `git checkout <hashcode>` to "time travel" into the commit
* ***Note:*** If you have GitLens, check the Commits view in the Source control tab to see the commit history.
## Revert one file to a previous state
*
### Reverting one file to a previous state
* Sometimes you want to revert just one file to its previous state
* For that, you need to figure out the commit hash of the state you want to return to
* 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*
* GitHub: check commits
* Then, run
* `git checkout <commit-hash> -- <filename>`
## Collaboration in Unity
* ***The zeroth rule:*** Make sure that everyone on team uses the same Unity and package versions.
* ***The first rule:*** Don't ever work on the same thing simultaneously.
* ***The second rule:*** When you do break rule #1, make necessary changes in communication so you won't break it again.
* Be sure to communicate about ***scene ownership***
* Scenes are not code files, so you can't easily merge changes if two people have worked on them
* Thus, the ***Scene Owner*** will be the only person on the team who should be working on a certain scene
* If a scene needs GameObject contributions from others, they can create prefabs that the Scene Owners then add to their scene
* Check commits from GitHub/GitLab
## Exercise 3. Branching team effort
<!--_class: "exercise invert" -->
* Work as a group for this assignment.
* Continue Exercise 2 from [Git basics](1-git-basics).
* Every group member creates an individual branch from the master, and makes some changes to the `GitTest.md` file.
* Add new files as well, at least one per group member.
* Do not tell other group members what you're going to change! :D
* Then, merge the changes back to the master branch. Fix ensuing conflicts, if any appear.
Work as a group for this assignment. Continue Exercise 2 from [Git basics](1-git-basics).
1) Every group member: create your own individual branch from the `main` branch
2) Then, make some changes to the `GitTest.md` file.
* Do not tell other group members what you're going to change! :D
3) Add new files as well, at least one file per group member.
4) Then, merge the changes back to the `main` branch. Fix ensuing conflicts, if any appear.
## Reading
@ -238,14 +259,25 @@ Continue the exercise from [Git Basics](1-git-basics) or create a new repository
* `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***
* Unlike merge, rebase applies changes from the rebased branch
***one commit at a time***
* Whenever there's a conflict:
1) After fixing the conflict, add the conflicting file with `git add <filename>`
2) Then continue the rebase process with `git rebase --continue`
3) If you want to disregard a conflicting commit, use `git rebase --skip`
4) If you get cold feet, you can cancel the rebase with `git rebase --abort`
* ***Note:*** A good link for [understanding rebase](https://borbware.github.io/unity-basics-course/project-management/2-git-continued-slides.html)
## Very extra: Interactive `git rebase -i`
<!-- _class: "extra invert" -->
* `git rebase` also has a hidden ***interactive*** mode used with `git 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](https://hackernoon.com/beginners-guide-to-interactive-rebasing-346a3f9c3a6d)