====== Using Git and GitLab with Visual Studio ====== ===== 1 Introduction to Git and GitLab ===== ==== 1.1 Introduction ==== Git is a distributed version-control system with server. A version-control system manages and keeps track of the modifications of the source files of a code (in this case, Lagamine). In a distributed system, the source files (*.F files) and the history of modifications are available on the computer of each developer, as well as on the [[https://gitlab.uliege.be/UEE/Lagamine|server]], which is the meeting point of all developers (). \\ \\ {{ :devs:use_fig1.png?nolink&400 |Schematic of Git}} In actual facts, the « original » code is the one on the server. Each developer owns a local copy, called a clone, that they can update when they connect to the server. By connecting to the server, developers can send their modifications and/or get the modifications done by other developers. ==== 1.2 Branching ==== Git gives the possibility to work with separate branches to allow developers to work on particular developments of the code without interfering with other developers, as illustrated in . The “master branch” can be considered as the official version of the code. Modifications should only be sent to this branch after they have been verified. \\ \\ {{ :devs:use_fig2.png?nolink&500 | Git branching}} \\ For Lagamine, the choice was made to create one branch for each developer. This way, every developer can work on the code in their own branch without having any impact on the other developers' work. However, it is important to regularly send your modifications on the server and to keep your branch up to date with the master branch to avoid conflicts (conflicts appear when 2 developers modify the same file at the same time). \\ \\ Each branch is initially a copy of the master branch. Each developer creates their branch on the server (GitLab) which they then clone on their computer. \\ A branch has two versions: * A distant version on the server, that everyone can see; * A local version on the developer’s computer, that they can modify as they wish. ==== 1.3 Basic Git commands ==== === 1.3.1 Commit === A « commit » is a validation of the modification. This validation is done locally, after the modification has been done and verified. Each commit is associated to an identification number, the date, the author, and a short message that summarizes the modifications (). Commits must be done regularly to keep track of the modifications as precisely as possible. \\ The message is written by the person making the commit. It should be brief and contain the essential information on the changes made to the code. \\ \\ {{ :devs:use_fig3.png?nolink&600 |A commit in GitLab}} === 1.3.2 Push and Pull === The "push" command is used to send commits to the server. Once the push is done, other developers can see the commits that were made on the pushed branch. A push is done between the local version and the distant version of the same branch (). \\ \\ The "pull" command is the opposite of the push: you get the commits from the server on your PC. A priori, this is not very useful since commits are normally made locally. However, this can be useful for developers who work on 2 separate machines – they will have 2 local versions of their branch (one on each computer) and will exchange modifications via the server. \\ \\ {{ :devs:use_fig4.png?nolink&600 |Push and pull}} \\ \\ **Remark:** There is also a "fetch" command, similar to the "pull". This command allows your computer to receive information about existing commits on the server without integrating them to the active branch. === 1.3.3 Merge === The "merge" command is used to merge two branches. The most common merge is the merging of a developer’s branch with the master branch. This way, the developer can add their commits in the official version of the code (). It is also possible to merge the master branch into your branch to retrieve commits from the official code into your branch. \\ \\ {{ :devs:use_fig5.png?nolink |Merging – Adding your modifications to the official code}} ===== 2 Using Git with Visual Studio ===== The interface of Visual Studio includes the basic functions of Git (commit, push, pull, merge). Making commits and exchanging data with the server is therefore very easy and does not require any additional software. ==== 2.1 Creating/Changing active branch ==== Once Git has been configured for Lagamine, you will have 2 local branches : the master branch and your own branch. You can however create additional branches locally (without creating them on the server) if you want to, for instance, create a feature that you are not completely certain about. \\ **NB:** If your feature ends up being good, you will have to merge that local branch into you own local branch to retrieve the modifications and commits. \\ \\ It is, however, easier to work only in the local version of your branch (the one you have on GitLab), especially if you are new to Git. \\ \\ To create a new branch, you simply need to click at the bottom right of the Visual Studio window as indicated in . From there you can access your different local branches (here “Helene” and “master”) and you can select the active branch (the one in which the modifications will be committed). You can also check the history of modifications of the active branch (= list of commits), and pull, fetch, or push commits. \\ :!: The active branch should __never__ be the master branch when you are modifying the code. To modify the official code, you must make commits in __your__ branch and then merge your branch with the master on the server. {{ :devs:use_fig6.png?nolink |Managing branches}} ==== 2.2 Viewing your changes ==== The source files that were modified but not committed will appear with a red tick on the left. To visualize the detailed changes that you made in a file, simply right-click on the file name in the solution explorer and select “Compare with Unmodified…” (In VS2019: Right click→Git→Compare with Unmodified…). Visual Studio will then display the unmodified and modified versions side-by-side with deletions appearing in red and additions in green, as shown in . {{ :devs:use_fig7.png?nolink |Viewing changes}} ==== 2.3 Commit ==== Once in your branch, you can modify the code and compile it as you wish (Debug or Release version). The Debug and Release executables will be placed in VS_Project\Lagamine\x64\Debug or \Release. As long as you don’t commit your changes, they will not be memorized by Git (but they will be saved locally on your computer if you use the "save" button in Visual Studio). === 2.3.1 Commiting all your changes === Once you are satisfied with some changes you made, you will have to commit them. Simply right-click on the modified subroutine in the solution explorer and select “Commit”. Visual Studio will then require you to write a short commit message describing the changes you’ve made see ), and than you will be able to click on “Commit all”. \\ {{ :devs:commit1.png?nolink |Commit message}} The commit should correspond to a modification or a group of coherent modifications. Commits must be made on a regular basis. The aim is to have a good monitoring of the evolutions of the code. Your commit messages should explicitly indicate what changes were made (not just “Modified subroutine XXXX.F”). === 2.3.2 Committing a part of your changes === Example: I modified the subroutine CHAB.F to correct some calculation, and I deleted useless comments in CHABDAM.F. These are two different changes that should be committed separately. In a first time, I am only going to commit the changes made in CHABDAM.F by using the 'indexing' function. Only the changes made to the indexed routines will be taken into account in the commit (see ). {{ :devs:commit2.png?nolink&600 |}} === 2.3.3 Cancel a local commit === :!: Use with caution \\ \\ If you committed changes without pushing the commit on the server, and you realize there is a mistake (wrong commit message, or some changes that should not have been committed were included in the commit), you have 2 solutions to undo the commit: * Reset and keep changes (--mixed) * Reset and delete changes (--hard) __Example__: I committed changes on CALMAT2 but I want to change my commit message. In , you can view the history of the branch. The red arrow « origin/Helene » indicates the last commit made on the distant branch. The arrow « Helene » indicates the last commit made on my local branch. My local branch is one commit ahead of the server. {{ :devs:commit3.png?nolink&600 |}} To reset my local branch and delete the last commit, I can right-click on the last commit of the server (here commit 6697b587 « ILAW=21 ; Lecture theta – IVAL 21 »), and select « Reset » and then chose between keeping or deleting changes. In my case, since I only want to change the commit message, I keep the changes so I can commit them again afterwards. \\ \\ :!: In practice, you could reset your branch to a state preceding the last commit on the server. However, by doing that, you will generate conflicts between the distant and local versions of your branch. These conflicts may turn out to be difficult to solve. For this reason, you should NEVER reset to points anterior to the last commit on the server. Consider that what is on the server is definitive. ==== 2.4 Merging ==== === 2.4.1 Merging the changes from the master === As indicated in section 2.1, pushing and pulling commits in the same branch can be done with the button on the bottom right of the Visual Studio window. In order to retrieve commits from another branch, the process is a bit more complex. \\ \\ First of all, make sure you don’t have any pending changes in your branch (otherwise they would be overwritten by the merge). Git will display an error message if that is the case and refuse the merge. You must either commit your changes or delete them. \\ \\ After that, you will have to retrieve commits from the server: set the master branch as your active branch and make a “pull” or a “fetch”. \\ \\ You can now merge your branch with the master. Set your branch as the active branch and select “Manage branches”. Right-click on your branch and choose “Merge from…”. In the Team Explorer tab, you will see a drop-down list from which you can select which branch you want to merge from. Select “origin/master” – it is the distant master branch. Remark: if you pulled the changes in your local master branch, selecting “master” or “origin/master” should be the same. \\ You can now click on “merge”. {{ :devs:merge1.png?nolink&700 |}} Merging the master branch into your branch should be done regularly to keep your version up to date. In particular, you must merge __before__ you make changes in a global subroutine (such as ELEMB, LOI2, LAMIN2, PRISIG, PRISUM, …) in order to avoid conflicts between the master and your branch. === 2.4.2 Merge conflicts === Example of a merge conflict : * The developper 1 added a call to a new law in LOI2 and merged his branch into the master branch; * I add a call to another new law in LOI2, using the LOI2 file that was not updated from the master branch (my LOI2 does not contain the call to the law of developer 1) If I try to merge my branch and the master, I will get a message indicating there is a merge conflict. Visual Studio will then suggest 3 possibilities to solve the conflict: * “Merge”: I will select manually which changes from each version of the code I want to keep; * “Take source”: I will take the version of the master branch and delete mine; * “Keep target”: I will keep my version and delete the one from the master. Generally, the 2 last options are not very useful. Indeed, if you consider the example above, this would mean deleting either the call to my law or the call to the law of developer 1. What we want here is a version with call to both laws. \\ \\ By selecting the “Merge” option, you can create a new version of the source file in conflict by selecting which lines you want to keep. In for instance, I combined 2 versions that each had a different comment written on the same line. I wanted to keep both comments, so I selected both (the on in the master version and the one in Dev2 version). A new version of the file is generated by visual studio. Once you are satisfied with the new version, you can save it and click on « Accept merge » in the top left corner. The merge can then be made without conflict. {{ :devs:merge2.png?nolink&600 |}} === 2.4.3 Merging your changes into the master === The Master branch is a protected branch, therefore merging into it can only be done on the GitLab website. \\ In order to make a merge with GitLab – that is, to put the modification from your branch into the official version of the code (master branch) – it is advised to first merge the master branch into your branch using Visual Studio (see section 2.4.2) to solve potential merge conflicts. \\ \\ To make the merge in GitLab, go to the Lagamine page ⟶ Repository ⟶ Branches. \\ \\ You can then click the « Merge request » button corresponding to your branch. You will then have to input a title for the merge (as done for the commits). ===== 3 Useful links ===== * Documentation on how to use Git in Visual Studio: https://docs.microsoft.com/en-us/azure/devops/repos/git/gitquickstart?view=azure-devops&tabs=visual-studio-2019 * GitLab documentation: https://docs.gitlab.com/ee/index.html