This page is intended to address commonly encountered problems when using git for Dynare development. A useful web page where you can find more information about the most commonly used git commands can be found on the Everyday GIT page.

NB: SHA stands for Secure Hash Algorithm. All you need to know about this is that it is a unique alphanumerical sequence that refers to a specific commit.

Problem 1: reverting local, uncommitted changes

Here you have modified one (or more) files and have now decided that you want to undo your changes. You have two options.

Undo all of the changes in one file

$ git checkout <<<filename>>>

This will obtain the version of the file at the top (origin/HEAD) of the central repository. If you would like to obtain the version of the file from another point in time, you must issue:

$ git checkout <<commit-SHA>> -- <<<filename>>>

Undo the changes in ALL modified files at once

$ git reset --hard

This will reset the state of the tracked files in your local repository to the state those files are in at origin/HEAD in the central repository, thereby discarding any changes you have made to these files. Files that are not tracked by git (i.e., those files not yet in the repository) will not be effected.

To change the state of your entire local repository to that of a previous commit, try

$ git reset --hard <<commit-SHA>>

NB: Be very careful when using this command, as it will irreversibly discard ALL of your changes to tracked files.

Problem 2: modifying files in local commits

In this situation, you have already made one or more local commits and wish to modify the files in any one of these commits. You may do this for any number of reasons, the primary ones being that there is a bug in a commit or that you forgot to apply the changes introduced by a commit to a certain file (and hence, must do that and add the file into the already existing commit). Take for example a repository that looks like:

---E---D---C---B---A

where each letter represents a commit with A being the most recent commit. Then there are two different procedures for modifying the commits, depending on whether the commit you want to modify is the most recent (A) or not (B,C,D or E)

The commit to modify is the most recent commit

Referencing the commit tree presented above, this subsection addresses how to modify commit A. After making the changes to the necessary files (either fixing bugs, or modifying files that you forgot to modify earlier), the procedure is as follows:

$ git add <<filename>>
$ git commit --amend

git add stages the modified files; this puts them on the list of files to add to the next commit.

git commit --amend Instead of creating a new commit for the staged files, issue this command to amend the previous commit. This will open up a text editor for you to modify the commit message if should desire to do so. Modify the message and save if desired. The commit will now include the changes you hadn't made earlier.

The commit to modify is back a ways in history

Referencing the commit tree presented above, this subsection addresses how to modify commit B,C,D or E. For concreteness, let's say we want to modify commit D. Before modifying the files that you want to commit, create a list of the SHAs of all of the commits that have come after the commit you wish to modify (you can use git GUI or the git log command to do this). After having done this, issue the command

git tag currentHead
git stash
git reset --hard <<<commit-SHA of commit D>>>

git tag currentHead will place a tag called currentHead at A. This will make it easier for you to reference this commit at a later date and will also keep it in the view of your git GUI when you view all branches.

git stash will save any git-tracked files that you may be working on at this time, as described on GitDailyWorkFlow.

git reset --hard <<<commit-SHA of commit D>>> will change all tracked files to their state at the time of commit D.

At this point, your local git repository will look like this:

---E---D

with commit D as the most recent commit. Now, you should modify the necessary files and amend commit D as described in the previous section.

After you have amended commit D, you are now ready to place your previous commits (A,B and C)on top of it. To do this, issue the following series of commands:

$ git cherry-pick <<commit-SHA of commit C>>
$ git cherry-pick <<commit-SHA of commit B>>
$ git cherry-pick <<commit-SHA of commit A>>

git cherry-pick <<commit-SHA of commit A>> will apply the commit A to the current branch. Hence, after this series of commands, the tree will look like

---E---D'---C---B---A

with D' representing the modified commit.

It is also important to note that you can easily change the order of your commits. If you were to issue the commands in this order:

$ git cherry-pick <<commit-SHA of commit B>>
$ git cherry-pick <<commit-SHA of commit C>>
$ git cherry-pick <<commit-SHA of commit A>>

your tree would look like:

---E---D'---B---C---A

Problem 3: modifying files in commits that have been pushed to your personal space

The procedure here is basically the same as in Problem 2 above with a few exceptions. First, if you are modifying a commit that is not the most recent, you will have to cherry-pick all commits that have come afterward. Second, when you have modified the commit history as you please (following the procedures above) you must issue the following command:

$ git push personal -f

to overwrite the previous commit history in your personal directory on Kirikou.

Problem 4: resolving conflicts

Git tracks changes in files by looking at the code surrounding modifications. This minimizes programming conflicts because often we do not have two people working on the same function (or, rather, the same parts of a function) at a given time. However, from time to time, this does happen and git will be unable to merge your changes with those of someone else and, hence, manual intervention may be required.

This situation will often arise when fetching and rebasing your local repository, but can also occur when cherry-picking (say, for example, you modify a historical commit by changing parts of a file that are later changed in another one of your commits).

When you encounter a merging conflict, git will edit the file with the conflict as follows (this is from a git cherry-pick conflict

<<<<<<< HEAD
        if options_.mh_posterior_mode_estimation
=======
        if ~options_.mh_posterior_mode_estimation
>>>>>>> 29f9bb9... Fixed bug related to the mh based approximation of the posterior covariance matrix (used

while this is from a git stash pop conflict

<<<<<<< Updated upstream
        if ~options_.mh_posterior_mode_estimation
=======
        if options_.mh_posterior_mode_estimation
>>>>>>> Stashed changes

Where, the part between <<<<<<< HEAD and ======= is what was already in your repository while the area between ======= and >>>>>>>... is what you were trying to place in its position. To deal with this manually, edit the file to contain the correct code (i.e. remove <<<<<<< HEAD, ======= and >>>>>>>...) and make sure that the code that remains is the correctly merged code.

If this is a git cherry-pick conflict, you will then issue the command

$ git add <<filename>>
$ git commit -c <<commit-SHA of the commit you were cherry-picking>>

if you want to maintain the commit message and authorship of the original commit.

If this is a git stash pop conflict you must edit the file as noted above then issue the command

git stash drop

to get rid of the stashed stack. If the file does differs from those in the central repository below it, you will have to commit the changes in a future commit. If they match exactly the changes in the central repository, there is nothing more to do.

DynareWiki: GitCommonProblems (last edited 2010-09-06 16:10:30 by HoutanBastani)