Difference between revisions of "How to do git tricks"
(→Filter) |
|||
(36 intermediate revisions by 2 users not shown) | |||
Line 3: | Line 3: | ||
==Find last commit where line existed== | ==Find last commit where line existed== | ||
<pre> | <pre> | ||
− | blame --reverse START | + | git blame --reverse START |
</pre> | </pre> | ||
+ | |||
==Comparing files== | ==Comparing files== | ||
From https://stackoverflow.com/questions/8131135/git-how-to-diff-two-different-files-in-different-branches | From https://stackoverflow.com/questions/8131135/git-how-to-diff-two-different-files-in-different-branches | ||
Line 13: | Line 14: | ||
==Compare and copy files from other branches== | ==Compare and copy files from other branches== | ||
− | https://stackoverflow.com/questions/2364147/how-to-get-just-one-file-from-another-branch | + | * https://stackoverflow.com/questions/2364147/how-to-get-just-one-file-from-another-branch |
+ | * https://stosb.com/blog/retaining-history-when-moving-files-across-repositories-in-git/ | ||
==Include branches from an unrelated repository== | ==Include branches from an unrelated repository== | ||
Line 25: | Line 27: | ||
The resulting repository has another unrelated history. | The resulting repository has another unrelated history. | ||
There is no need for the two repositories to have a common initial commit or anything. | There is no need for the two repositories to have a common initial commit or anything. | ||
− | The commit hashes are preserved. You can even <tt>git cherry-pick</tt> commit from the other repostory and git will do pretty good job finding files to apply the commits to, even if the files have somewhat different names and are in somewhat different locations in the | + | The commit hashes are preserved. You can even <tt>git cherry-pick</tt> commit from the other repostory and git will often do a pretty good job finding files to apply the commits to, even if the files have somewhat different names and are in somewhat different locations in the two file trees. |
==Using git cherry pick== | ==Using git cherry pick== | ||
===Across unrelated histories=== | ===Across unrelated histories=== | ||
After importing branches from another unrelated repository as an unrelated history, | After importing branches from another unrelated repository as an unrelated history, | ||
− | <tt>git cherry</tt> pick can apply a commit from the unrelated history, but | + | <tt>git cherry</tt> pick can apply a commit from the unrelated history, but |
− | + | sometimes git cherry-pick will work across files having different paths and sometimes it just creates copies on new paths, which is not helpful. Not sure why. The same cherry-pick on different computers can do different things on the same repository and same commits for some reason. | |
− | + | ||
+ | ===Review changes before commit=== | ||
+ | Be sure to do | ||
<pre> | <pre> | ||
− | git diff HEAD | + | git diff HEAD |
</pre> | </pre> | ||
+ | or | ||
+ | <pre> | ||
+ | git diff <your base> | ||
+ | </pre> | ||
+ | for multiple commits piled on top of <tt><your base></tt> | ||
to review what changes are being made and to minimize them. <tt>git diff</tt> seems to produce misleading results. | to review what changes are being made and to minimize them. <tt>git diff</tt> seems to produce misleading results. | ||
− | ===Undesirable changes from | + | ===Undesirable changes from commits=== |
− | Often git cherry pick will make more changes including those from other commits | + | * Often git cherry pick will make more changes including those from other commits. Here is why: [https://stackoverflow.com/questions/7802252/why-cherry-pick-pick-change-more-than-one-commit Git goes back in the history until the cherry pick source matches the target and creates the patch based on this revision. That's why more changes might appear.] |
+ | * In a series of cherry-picked commit, '''do not make additional changes on the modified lines'''. The following cherry-picked commit will put them back! You have to make them all at once after you are done. | ||
− | == | + | One more reason why it is important to [[#Review changes before commit|review changes before commit]] and edit as needed, not just resolve the conflict. |
+ | |||
+ | ==Using patch files== | ||
===Instead of cherry-pick=== | ===Instead of cherry-pick=== | ||
− | + | * Generate and use patch | |
<pre> | <pre> | ||
− | git log -p -1 <sha1-of-your-commit> | + | git log -p -1 <sha1> | git apply --3way - |
+ | </pre> | ||
+ | But this seems to make much the same changes and can pull more changes too. The --3way flag will mark conflicts, without --3way aplying the patch just failed for me. | ||
+ | |||
+ | * Create a patch file | ||
+ | <pre> | ||
+ | git log -p -1 <sha1-of-your-commit> > patch.file | ||
</pre> | </pre> | ||
− | then | + | edit it manually as desired and then apply the patch: |
<pre> | <pre> | ||
− | + | it apply --3way patch.file | |
</pre> | </pre> | ||
− | + | ||
===[https://www.codefull.org/2018/11/specify-target-file-in-git-cherry-pick To modify only one file]=== | ===[https://www.codefull.org/2018/11/specify-target-file-in-git-cherry-pick To modify only one file]=== | ||
Line 63: | Line 81: | ||
git apply --3way patchfile | git apply --3way patchfile | ||
</pre> | </pre> | ||
+ | |||
+ | ==Merging unrelated histories== | ||
+ | * https://git-scm.com/book/en/v1/Git-Tools-Subtree-Merging | ||
+ | * https://help.github.com/en/articles/about-git-subtree-merges | ||
+ | * https://medium.com/@spences10/git-allow-unrelated-histories-a39a3814b981 | ||
+ | * https://stackoverflow.com/questions/37937984/git-refusing-to-merge-unrelated-histories-on-rebase | ||
+ | * https://stackoverflow.com/questions/13040958/merge-two-git-repositories-without-breaking-file-history | ||
+ | * https://stosb.com/blog/retaining-history-when-moving-files-across-repositories-in-git/ | ||
+ | * https://stackoverflow.com/questions/16937359/git-copy-file-preserving-history | ||
+ | * https://stackoverflow.com/questions/6434995/how-to-re-merge-a-file-in-the-git | ||
+ | |||
+ | ==Filter== | ||
+ | * https://manishearth.github.io/blog/2017/03/05/understanding-git-filter-branch/ | ||
+ | ** to extract a subdirectory: git filter-branch --subdirectory-filter name_of_subdir @ | ||
+ | * https://stackoverflow.com/questions/7430717/git-filter-branch-on-all-branches | ||
+ | * https://git-scm.com/docs/git-filter-branch | ||
+ | * https://github.com/newren/git-filter-repo/ | ||
+ | |||
+ | ===Filter subdirectory=== | ||
+ | <pre> | ||
+ | mkdir wrf-fire-filtered | ||
+ | cd wrf-fire-filtered | ||
+ | git clone --bare github:/openwfm/wrf-fire.git .git | ||
+ | git config --bool core.bare false | ||
+ | git reset --hard | ||
+ | git filter-branch --subdirectory-filter wrfv2_fire --prune-empty --tag-name-filter cat -- --all | ||
+ | git remote add filtered git@github.com:janmandel/wrf-fire-filtered.git | ||
+ | git push filtered --mirror | ||
+ | </pre> | ||
+ | |||
+ | ==Submodules== | ||
+ | * https://git-scm.com/book/en/v2/Git-Tools-Submodules | ||
+ | ==See also== | ||
+ | * [https://git-scm.com/docs/git-cherry-pick git cherry pick man page] | ||
+ | * [https://git-scm.com/docs/git-diff git diff man page] | ||
+ | * https://randyfay.com/content/avoiding-git-disasters-gory-story | ||
+ | * https://www.git-scm.com/docs/git-mergetool | ||
+ | * [https://gist.github.com/karenyyng/f19ff75c60f18b4b8149#file-git_mergetool_tutorial-md git mergetool tutorial] | ||
+ | * https://git-blame.blogspot.com/2013/09/fun-with-first-parent-history.html |
Latest revision as of 23:32, 29 February 2020
Find last commit where line existed
git blame --reverse START
Comparing files
git diff branch1:full/path/to/foo.txt branch2:full/path/to/foo-another.txt
How to link to such comparison view on github?
Compare and copy files from other branches
- https://stackoverflow.com/questions/2364147/how-to-get-just-one-file-from-another-branch
- https://stosb.com/blog/retaining-history-when-moving-files-across-repositories-in-git/
git remote add rep2-git url_to_unrelated_repository git fetch rep2-git git checkout remotes/rep2-git/branch2 git checkout -b rep2/branch2 git push -u origin rep2/branch2:rep2/branch2
The resulting repository has another unrelated history. There is no need for the two repositories to have a common initial commit or anything. The commit hashes are preserved. You can even git cherry-pick commit from the other repostory and git will often do a pretty good job finding files to apply the commits to, even if the files have somewhat different names and are in somewhat different locations in the two file trees.
Using git cherry pick
After importing branches from another unrelated repository as an unrelated history, git cherry pick can apply a commit from the unrelated history, but sometimes git cherry-pick will work across files having different paths and sometimes it just creates copies on new paths, which is not helpful. Not sure why. The same cherry-pick on different computers can do different things on the same repository and same commits for some reason.
Review changes before commit
Be sure to do
git diff HEAD
or
git diff <your base>
for multiple commits piled on top of <your base> to review what changes are being made and to minimize them. git diff seems to produce misleading results.
Undesirable changes from commits
- Often git cherry pick will make more changes including those from other commits. Here is why: Git goes back in the history until the cherry pick source matches the target and creates the patch based on this revision. That's why more changes might appear.
- In a series of cherry-picked commit, do not make additional changes on the modified lines. The following cherry-picked commit will put them back! You have to make them all at once after you are done.
One more reason why it is important to review changes before commit and edit as needed, not just resolve the conflict.
Using patch files
Instead of cherry-pick
- Generate and use patch
git log -p -1 <sha1> | git apply --3way -
But this seems to make much the same changes and can pull more changes too. The --3way flag will mark conflicts, without --3way aplying the patch just failed for me.
- Create a patch file
git log -p -1 <sha1-of-your-commit> > patch.file
edit it manually as desired and then apply the patch:
it apply --3way patch.file
To modify only one file
- Create a patch file for that individual file:
git show [commit hash] -- path/to/old/file > patchfile
- Manually edit the newly created patchfile and replace all occurrences of the old path with the new path.
- Apply the patch via
git apply --3way patchfile
- https://git-scm.com/book/en/v1/Git-Tools-Subtree-Merging
- https://help.github.com/en/articles/about-git-subtree-merges
- https://medium.com/@spences10/git-allow-unrelated-histories-a39a3814b981
- https://stackoverflow.com/questions/37937984/git-refusing-to-merge-unrelated-histories-on-rebase
- https://stackoverflow.com/questions/13040958/merge-two-git-repositories-without-breaking-file-history
- https://stosb.com/blog/retaining-history-when-moving-files-across-repositories-in-git/
- https://stackoverflow.com/questions/16937359/git-copy-file-preserving-history
- https://stackoverflow.com/questions/6434995/how-to-re-merge-a-file-in-the-git
Filter
- https://manishearth.github.io/blog/2017/03/05/understanding-git-filter-branch/
- to extract a subdirectory: git filter-branch --subdirectory-filter name_of_subdir @
- https://stackoverflow.com/questions/7430717/git-filter-branch-on-all-branches
- https://git-scm.com/docs/git-filter-branch
- https://github.com/newren/git-filter-repo/
Filter subdirectory
mkdir wrf-fire-filtered cd wrf-fire-filtered git clone --bare github:/openwfm/wrf-fire.git .git git config --bool core.bare false git reset --hard git filter-branch --subdirectory-filter wrfv2_fire --prune-empty --tag-name-filter cat -- --all git remote add filtered git@github.com:janmandel/wrf-fire-filtered.git git push filtered --mirror