#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC target("sse4")
using namespace std;
struct GaussianUnionFind {
  vector<int> parent, rank, dist, base;
  vector<pair<int*, int> > undo;
  GaussianUnionFind(int size = 200200) {
    parent.resize(size);
    iota(parent.begin(), parent.end(), 0);
    rank.assign(size, 0);
    dist.assign(size, 0);
    base.assign(30, 0);
  }
  int now() { return undo.size(); }
  pair<int, int> find(int x) {
    int res = 0;
    while (x != parent[x]) {
      res ^= dist[x];
      x = parent[x];
    }
    return make_pair(x, res);
  }
  void addGauss(int w) {
    for (int e = 29; e >= 0; e--) {
      if (base[e] == 0 && (w & (1 << e))) {
        undo.push_back({&base[e], base[e]});
        base[e] = w;
        return;
      }
      w = min(w, w ^ base[e]);
    }
  }
  int getGauss(int w) {
    for (int e = 29; e >= 0; e--) w = min(w, w ^ base[e]);
    return w;
  }
  void join(int u, int v, int w) {
    int cost_u, cost_v;
    tie(u, cost_u) = find(u);
    tie(v, cost_v) = find(v);
    w ^= cost_u ^ cost_v;
    if (u == v) {
      addGauss(w);
    } else {
      if (rank[u] > rank[v]) swap(u, v);
      undo.push_back({&parent[u], parent[u]});
      parent[u] = v;
      undo.push_back({&dist[u], dist[u]});
      dist[u] = w;
      if (rank[u] == rank[v]) {
        undo.push_back({&rank[v], rank[v]});
        rank[v]++;
      }
    }
  }
  int get(int u, int v) {
    int cost_u, cost_v;
    tie(u, cost_u) = find(u);
    tie(v, cost_v) = find(v);
    assert(u == v);
    return getGauss(cost_u ^ cost_v);
  }
  void roll(int when) {
    for (int e = undo.size() - 1; e >= when; e--)
      *undo[e].first = undo[e].second;
    undo.resize(when);
  }
};
struct edge {
  int ty, u, v, w, start, end, res;
};
const int maxn = 400400;
edge link[maxn];
GaussianUnionFind dsu;
void solve(int l, int r) {
  if (l == r) return;
  if (l + 1 == r) {
    if (!link[l].ty) link[l].res = dsu.get(link[l].u, link[l].v);
    return;
  }
  int m = (l + r) >> 1;
  int now = dsu.now();
  for (int e = m; e < r; e++) {
    if (link[e].ty == 2 && link[e].start < l) {
      dsu.join(link[e].u, link[e].v, link[e].w);
    }
  }
  solve(l, m);
  dsu.roll(now);
  for (int e = l; e < m; e++) {
    if (link[e].ty == 1 && link[e].end >= r) {
      dsu.join(link[e].u, link[e].v, link[e].w);
    }
  }
  solve(m, r);
  dsu.roll(now);
}
int main() {
  map<pair<int, int>, int> when;
  int n, m;
  scanf("%d %d", &n, &m);
  for (int e = 0; e < m; e++) {
    int u, v, w;
    scanf("%d %d %d", &u, &v, &w);
    if (u > v) swap(u, v);
    link[e] = {1, u, v, w, e, maxn - 1, 0};
    when[{u, v}] = e;
  }
  int q;
  scanf("%d", &q);
  for (int e = 0; e < q; e++) {
    int ty, u, v;
    scanf("%d %d %d", &ty, &u, &v);
    if (u > v) swap(u, v);
    if (ty == 1) {
      int w;
      scanf("%d", &w);
      link[e + m] = {1, u, v, w, e, maxn - 1, 0};
      when[{u, v}] = e + m;
    } else if (ty == 2) {
      auto it = when.find({u, v});
      assert(it != when.end());
      link[it->second].end = e + m;
      link[e + m] = {2, u, v, link[it->second].w, it->second, e + m, 0};
      when.erase(it);
    } else {
      link[e + m] = {0, u, v, 0, 0, 0, 0};
    }
  }
  solve(0, q + m);
  for (int e = 0; e < q + m; e++)
    if (!link[e].ty) printf("%d\n", link[e].res);
  return 0;
}
